wRMSG
qcustomplot.cpp
Idź do dokumentacji tego pliku.
1 /***************************************************************************
2 ** **
3 ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 ** Copyright (C) 2011-2021 Emanuel Eichhammer **
5 ** **
6 ** This program is free software: you can redistribute it and/or modify **
7 ** it under the terms of the GNU General Public License as published by **
8 ** the Free Software Foundation, either version 3 of the License, or **
9 ** (at your option) any later version. **
10 ** **
11 ** This program is distributed in the hope that it will be useful, **
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 ** GNU General Public License for more details. **
15 ** **
16 ** You should have received a copy of the GNU General Public License **
17 ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 ** **
19 ****************************************************************************
20 ** Author: Emanuel Eichhammer **
21 ** Website/Contact: http://www.qcustomplot.com/ **
22 ** Date: 29.03.21 **
23 ** Version: 2.1.0 **
24 ****************************************************************************/
25 
26 #include "inc/qcustomplot.h"
27 
28 
29 /* including file 'src/vector2d.cpp' */
30 /* modified 2021-03-29T02:30:44, size 7973 */
31 
35 
43 /* start documentation of inline functions */
44 
113 /* end documentation of inline functions */
114 
119  mX(0),
120  mY(0)
121 {
122 }
123 
128 QCPVector2D::QCPVector2D(double x, double y) :
129  mX(x),
130  mY(y)
131 {
132 }
133 
138 QCPVector2D::QCPVector2D(const QPoint &point) :
139  mX(point.x()),
140  mY(point.y())
141 {
142 }
143 
148 QCPVector2D::QCPVector2D(const QPointF &point) :
149  mX(point.x()),
150  mY(point.y())
151 {
152 }
153 
162 {
163  if (mX == 0.0 && mY == 0.0) return;
164  const double lenInv = 1.0/length();
165  mX *= lenInv;
166  mY *= lenInv;
167 }
168 
177 {
178  if (mX == 0.0 && mY == 0.0) return *this;
179  const double lenInv = 1.0/length();
180  return QCPVector2D(mX*lenInv, mY*lenInv);
181 }
182 
190 double QCPVector2D::distanceSquaredToLine(const QCPVector2D &start, const QCPVector2D &end) const
191 {
192  const QCPVector2D v(end-start);
193  const double vLengthSqr = v.lengthSquared();
194  if (!qFuzzyIsNull(vLengthSqr))
195  {
196  const double mu = v.dot(*this-start)/vLengthSqr;
197  if (mu < 0)
198  return (*this-start).lengthSquared();
199  else if (mu > 1)
200  return (*this-end).lengthSquared();
201  else
202  return ((start + mu*v)-*this).lengthSquared();
203  } else
204  return (*this-start).lengthSquared();
205 }
206 
214 double QCPVector2D::distanceSquaredToLine(const QLineF &line) const
215 {
216  return distanceSquaredToLine(QCPVector2D(line.p1()), QCPVector2D(line.p2()));
217 }
218 
225 double QCPVector2D::distanceToStraightLine(const QCPVector2D &base, const QCPVector2D &direction) const
226 {
227  return qAbs((*this-base).dot(direction.perpendicular()))/direction.length();
228 }
229 
235 {
236  mX *= factor;
237  mY *= factor;
238  return *this;
239 }
240 
246 {
247  mX /= divisor;
248  mY /= divisor;
249  return *this;
250 }
251 
256 {
257  mX += vector.mX;
258  mY += vector.mY;
259  return *this;
260 }
261 
266 {
267  mX -= vector.mX;
268  mY -= vector.mY;
269  return *this;
270 }
271 /* end of 'src/vector2d.cpp' */
272 
273 
274 /* including file 'src/painter.cpp' */
275 /* modified 2021-03-29T02:30:44, size 8656 */
276 
280 
298  mModes(pmDefault),
299  mIsAntialiasing(false)
300 {
301  // don't setRenderHint(QPainter::NonCosmeticDefautPen) here, because painter isn't active yet and
302  // a call to begin() will follow
303 }
304 
311 QCPPainter::QCPPainter(QPaintDevice *device) :
312  QPainter(device),
313  mModes(pmDefault),
314  mIsAntialiasing(false)
315 {
316 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
317  if (isActive())
318  setRenderHint(QPainter::NonCosmeticDefaultPen);
319 #endif
320 }
321 
328 void QCPPainter::setPen(const QPen &pen)
329 {
330  QPainter::setPen(pen);
331  if (mModes.testFlag(pmNonCosmetic))
332  makeNonCosmetic();
333 }
334 
342 void QCPPainter::setPen(const QColor &color)
343 {
344  QPainter::setPen(color);
345  if (mModes.testFlag(pmNonCosmetic))
346  makeNonCosmetic();
347 }
348 
356 void QCPPainter::setPen(Qt::PenStyle penStyle)
357 {
358  QPainter::setPen(penStyle);
359  if (mModes.testFlag(pmNonCosmetic))
360  makeNonCosmetic();
361 }
362 
371 void QCPPainter::drawLine(const QLineF &line)
372 {
373  if (mIsAntialiasing || mModes.testFlag(pmVectorized))
374  QPainter::drawLine(line);
375  else
376  QPainter::drawLine(line.toLine());
377 }
378 
385 void QCPPainter::setAntialiasing(bool enabled)
386 {
387  setRenderHint(QPainter::Antialiasing, enabled);
388  if (mIsAntialiasing != enabled)
389  {
390  mIsAntialiasing = enabled;
391  if (!mModes.testFlag(pmVectorized)) // antialiasing half-pixel shift only needed for rasterized outputs
392  {
393  if (mIsAntialiasing)
394  translate(0.5, 0.5);
395  else
396  translate(-0.5, -0.5);
397  }
398  }
399 }
400 
405 void QCPPainter::setModes(QCPPainter::PainterModes modes)
406 {
407  mModes = modes;
408 }
409 
421 bool QCPPainter::begin(QPaintDevice *device)
422 {
423  bool result = QPainter::begin(device);
424 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
425  if (result)
426  setRenderHint(QPainter::NonCosmeticDefaultPen);
427 #endif
428  return result;
429 }
430 
437 {
438  if (!enabled && mModes.testFlag(mode))
439  mModes &= ~mode;
440  else if (enabled && !mModes.testFlag(mode))
441  mModes |= mode;
442 }
443 
453 {
455  QPainter::save();
456 }
457 
467 {
468  if (!mAntialiasingStack.isEmpty())
470  else
471  qDebug() << Q_FUNC_INFO << "Unbalanced save/restore";
472  QPainter::restore();
473 }
474 
480 {
481  if (qFuzzyIsNull(pen().widthF()))
482  {
483  QPen p = pen();
484  p.setWidth(1);
485  QPainter::setPen(p);
486  }
487 }
488 /* end of 'src/painter.cpp' */
489 
490 
491 /* including file 'src/paintbuffer.cpp' */
492 /* modified 2021-03-29T02:30:44, size 18915 */
493 
497 
518 /* start documentation of pure virtual functions */
519 
561 /* end documentation of pure virtual functions */
562 /* start documentation of inline functions */
563 
574 /* end documentation of inline functions */
575 
581 QCPAbstractPaintBuffer::QCPAbstractPaintBuffer(const QSize &size, double devicePixelRatio) :
582  mSize(size),
583  mDevicePixelRatio(devicePixelRatio),
584  mInvalidated(true)
585 {
586 }
587 
589 {
590 }
591 
600 void QCPAbstractPaintBuffer::setSize(const QSize &size)
601 {
602  if (mSize != size)
603  {
604  mSize = size;
606  }
607 }
608 
625 {
627 }
628 
639 {
640  if (!qFuzzyCompare(ratio, mDevicePixelRatio))
641  {
642 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
643  mDevicePixelRatio = ratio;
645 #else
646  qDebug() << Q_FUNC_INFO << "Device pixel ratios not supported for Qt versions before 5.4";
647  mDevicePixelRatio = 1.0;
648 #endif
649  }
650 }
651 
655 
667 QCPPaintBufferPixmap::QCPPaintBufferPixmap(const QSize &size, double devicePixelRatio) :
668  QCPAbstractPaintBuffer(size, devicePixelRatio)
669 {
671 }
672 
674 {
675 }
676 
677 /* inherits documentation from base class */
679 {
680  QCPPainter *result = new QCPPainter(&mBuffer);
681 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
682  result->setRenderHint(QPainter::HighQualityAntialiasing);
683 #endif
684  return result;
685 }
686 
687 /* inherits documentation from base class */
689 {
690  if (painter && painter->isActive())
691  painter->drawPixmap(0, 0, mBuffer);
692  else
693  qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed";
694 }
695 
696 /* inherits documentation from base class */
698 {
699  mBuffer.fill(color);
700 }
701 
702 /* inherits documentation from base class */
704 {
705  setInvalidated();
706  if (!qFuzzyCompare(1.0, mDevicePixelRatio))
707  {
708 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
709  mBuffer = QPixmap(mSize*mDevicePixelRatio);
710  mBuffer.setDevicePixelRatio(mDevicePixelRatio);
711 #else
712  qDebug() << Q_FUNC_INFO << "Device pixel ratios not supported for Qt versions before 5.4";
713  mDevicePixelRatio = 1.0;
714  mBuffer = QPixmap(mSize);
715 #endif
716  } else
717  {
718  mBuffer = QPixmap(mSize);
719  }
720 }
721 
722 
723 #ifdef QCP_OPENGL_PBUFFER
724 
747 QCPPaintBufferGlPbuffer::QCPPaintBufferGlPbuffer(const QSize &size, double devicePixelRatio, int multisamples) :
748  QCPAbstractPaintBuffer(size, devicePixelRatio),
749  mGlPBuffer(0),
750  mMultisamples(qMax(0, multisamples))
751 {
752  QCPPaintBufferGlPbuffer::reallocateBuffer();
753 }
754 
755 QCPPaintBufferGlPbuffer::~QCPPaintBufferGlPbuffer()
756 {
757  if (mGlPBuffer)
758  delete mGlPBuffer;
759 }
760 
761 /* inherits documentation from base class */
762 QCPPainter *QCPPaintBufferGlPbuffer::startPainting()
763 {
764  if (!mGlPBuffer->isValid())
765  {
766  qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
767  return 0;
768  }
769 
770  QCPPainter *result = new QCPPainter(mGlPBuffer);
771  result->setRenderHint(QPainter::HighQualityAntialiasing);
772  return result;
773 }
774 
775 /* inherits documentation from base class */
776 void QCPPaintBufferGlPbuffer::draw(QCPPainter *painter) const
777 {
778  if (!painter || !painter->isActive())
779  {
780  qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed";
781  return;
782  }
783  if (!mGlPBuffer->isValid())
784  {
785  qDebug() << Q_FUNC_INFO << "OpenGL pbuffer isn't valid, reallocateBuffer was not called?";
786  return;
787  }
788  painter->drawImage(0, 0, mGlPBuffer->toImage());
789 }
790 
791 /* inherits documentation from base class */
792 void QCPPaintBufferGlPbuffer::clear(const QColor &color)
793 {
794  if (mGlPBuffer->isValid())
795  {
796  mGlPBuffer->makeCurrent();
797  glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
798  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
799  mGlPBuffer->doneCurrent();
800  } else
801  qDebug() << Q_FUNC_INFO << "OpenGL pbuffer invalid or context not current";
802 }
803 
804 /* inherits documentation from base class */
805 void QCPPaintBufferGlPbuffer::reallocateBuffer()
806 {
807  if (mGlPBuffer)
808  delete mGlPBuffer;
809 
810  QGLFormat format;
811  format.setAlpha(true);
812  format.setSamples(mMultisamples);
813  mGlPBuffer = new QGLPixelBuffer(mSize, format);
814 }
815 #endif // QCP_OPENGL_PBUFFER
816 
817 
818 #ifdef QCP_OPENGL_FBO
819 
843 QCPPaintBufferGlFbo::QCPPaintBufferGlFbo(const QSize &size, double devicePixelRatio, QWeakPointer<QOpenGLContext> glContext, QWeakPointer<QOpenGLPaintDevice> glPaintDevice) :
844  QCPAbstractPaintBuffer(size, devicePixelRatio),
845  mGlContext(glContext),
846  mGlPaintDevice(glPaintDevice),
847  mGlFrameBuffer(0)
848 {
849  QCPPaintBufferGlFbo::reallocateBuffer();
850 }
851 
852 QCPPaintBufferGlFbo::~QCPPaintBufferGlFbo()
853 {
854  if (mGlFrameBuffer)
855  delete mGlFrameBuffer;
856 }
857 
858 /* inherits documentation from base class */
859 QCPPainter *QCPPaintBufferGlFbo::startPainting()
860 {
861  QSharedPointer<QOpenGLPaintDevice> paintDevice = mGlPaintDevice.toStrongRef();
862  QSharedPointer<QOpenGLContext> context = mGlContext.toStrongRef();
863  if (!paintDevice)
864  {
865  qDebug() << Q_FUNC_INFO << "OpenGL paint device doesn't exist";
866  return 0;
867  }
868  if (!context)
869  {
870  qDebug() << Q_FUNC_INFO << "OpenGL context doesn't exist";
871  return 0;
872  }
873  if (!mGlFrameBuffer)
874  {
875  qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
876  return 0;
877  }
878 
879  if (QOpenGLContext::currentContext() != context.data())
880  context->makeCurrent(context->surface());
881  mGlFrameBuffer->bind();
882  QCPPainter *result = new QCPPainter(paintDevice.data());
883 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
884  result->setRenderHint(QPainter::HighQualityAntialiasing);
885 #endif
886  return result;
887 }
888 
889 /* inherits documentation from base class */
890 void QCPPaintBufferGlFbo::donePainting()
891 {
892  if (mGlFrameBuffer && mGlFrameBuffer->isBound())
893  mGlFrameBuffer->release();
894  else
895  qDebug() << Q_FUNC_INFO << "Either OpenGL frame buffer not valid or was not bound";
896 }
897 
898 /* inherits documentation from base class */
899 void QCPPaintBufferGlFbo::draw(QCPPainter *painter) const
900 {
901  if (!painter || !painter->isActive())
902  {
903  qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed";
904  return;
905  }
906  if (!mGlFrameBuffer)
907  {
908  qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
909  return;
910  }
911  painter->drawImage(0, 0, mGlFrameBuffer->toImage());
912 }
913 
914 /* inherits documentation from base class */
915 void QCPPaintBufferGlFbo::clear(const QColor &color)
916 {
917  QSharedPointer<QOpenGLContext> context = mGlContext.toStrongRef();
918  if (!context)
919  {
920  qDebug() << Q_FUNC_INFO << "OpenGL context doesn't exist";
921  return;
922  }
923  if (!mGlFrameBuffer)
924  {
925  qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
926  return;
927  }
928 
929  if (QOpenGLContext::currentContext() != context.data())
930  context->makeCurrent(context->surface());
931  mGlFrameBuffer->bind();
932  glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
933  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
934  mGlFrameBuffer->release();
935 }
936 
937 /* inherits documentation from base class */
938 void QCPPaintBufferGlFbo::reallocateBuffer()
939 {
940  // release and delete possibly existing framebuffer:
941  if (mGlFrameBuffer)
942  {
943  if (mGlFrameBuffer->isBound())
944  mGlFrameBuffer->release();
945  delete mGlFrameBuffer;
946  mGlFrameBuffer = 0;
947  }
948 
949  QSharedPointer<QOpenGLPaintDevice> paintDevice = mGlPaintDevice.toStrongRef();
950  QSharedPointer<QOpenGLContext> context = mGlContext.toStrongRef();
951  if (!paintDevice)
952  {
953  qDebug() << Q_FUNC_INFO << "OpenGL paint device doesn't exist";
954  return;
955  }
956  if (!context)
957  {
958  qDebug() << Q_FUNC_INFO << "OpenGL context doesn't exist";
959  return;
960  }
961 
962  // create new fbo with appropriate size:
963  context->makeCurrent(context->surface());
964  QOpenGLFramebufferObjectFormat frameBufferFormat;
965  frameBufferFormat.setSamples(context->format().samples());
966  frameBufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
967  mGlFrameBuffer = new QOpenGLFramebufferObject(mSize*mDevicePixelRatio, frameBufferFormat);
968  if (paintDevice->size() != mSize*mDevicePixelRatio)
969  paintDevice->setSize(mSize*mDevicePixelRatio);
970 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
971  paintDevice->setDevicePixelRatio(mDevicePixelRatio);
972 #endif
973 }
974 #endif // QCP_OPENGL_FBO
975 /* end of 'src/paintbuffer.cpp' */
976 
977 
978 /* including file 'src/layer.cpp' */
979 /* modified 2021-03-29T02:30:44, size 37615 */
980 
984 
1041 /* start documentation of inline functions */
1042 
1057 /* end documentation of inline functions */
1058 
1067 QCPLayer::QCPLayer(QCustomPlot *parentPlot, const QString &layerName) :
1068  QObject(parentPlot),
1069  mParentPlot(parentPlot),
1070  mName(layerName),
1071  mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function
1072  mVisible(true),
1073  mMode(lmLogical)
1074 {
1075  // Note: no need to make sure layerName is unique, because layer
1076  // management is done with QCustomPlot functions.
1077 }
1078 
1080 {
1081  // If child layerables are still on this layer, detach them, so they don't try to reach back to this
1082  // then invalid layer once they get deleted/moved themselves. This only happens when layers are deleted
1083  // directly, like in the QCustomPlot destructor. (The regular layer removal procedure for the user is to
1084  // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.)
1085 
1086  while (!mChildren.isEmpty())
1087  mChildren.last()->setLayer(nullptr); // removes itself from mChildren via removeChild()
1088 
1089  if (mParentPlot->currentLayer() == this)
1090  qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or nullptr beforehand.";
1091 }
1092 
1101 void QCPLayer::setVisible(bool visible)
1102 {
1103  mVisible = visible;
1104 }
1105 
1128 {
1129  if (mMode != mode)
1130  {
1131  mMode = mode;
1132  if (QSharedPointer<QCPAbstractPaintBuffer> pb = mPaintBuffer.toStrongRef())
1133  pb->setInvalidated();
1134  }
1135 }
1136 
1144 {
1145  foreach (QCPLayerable *child, mChildren)
1146  {
1147  if (child->realVisibility())
1148  {
1149  painter->save();
1150  painter->setClipRect(child->clipRect().translated(0, -1));
1151  child->applyDefaultAntialiasingHint(painter);
1152  child->draw(painter);
1153  painter->restore();
1154  }
1155  }
1156 }
1157 
1167 {
1168  if (QSharedPointer<QCPAbstractPaintBuffer> pb = mPaintBuffer.toStrongRef())
1169  {
1170  if (QCPPainter *painter = pb->startPainting())
1171  {
1172  if (painter->isActive())
1173  draw(painter);
1174  else
1175  qDebug() << Q_FUNC_INFO << "paint buffer returned inactive painter";
1176  delete painter;
1177  pb->donePainting();
1178  } else
1179  qDebug() << Q_FUNC_INFO << "paint buffer returned nullptr painter";
1180  } else
1181  qDebug() << Q_FUNC_INFO << "no valid paint buffer associated with this layer";
1182 }
1183 
1199 {
1201  {
1202  if (QSharedPointer<QCPAbstractPaintBuffer> pb = mPaintBuffer.toStrongRef())
1203  {
1204  pb->clear(Qt::transparent);
1206  pb->setInvalidated(false); // since layer is lmBuffered, we know only this layer is on buffer and we can reset invalidated flag
1207  mParentPlot->update();
1208  } else
1209  qDebug() << Q_FUNC_INFO << "no valid paint buffer associated with this layer";
1210  } else
1211  mParentPlot->replot();
1212 }
1213 
1224 void QCPLayer::addChild(QCPLayerable *layerable, bool prepend)
1225 {
1226  if (!mChildren.contains(layerable))
1227  {
1228  if (prepend)
1229  mChildren.prepend(layerable);
1230  else
1231  mChildren.append(layerable);
1232  if (QSharedPointer<QCPAbstractPaintBuffer> pb = mPaintBuffer.toStrongRef())
1233  pb->setInvalidated();
1234  } else
1235  qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast<quintptr>(layerable);
1236 }
1237 
1248 {
1249  if (mChildren.removeOne(layerable))
1250  {
1251  if (QSharedPointer<QCPAbstractPaintBuffer> pb = mPaintBuffer.toStrongRef())
1252  pb->setInvalidated();
1253  } else
1254  qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast<quintptr>(layerable);
1255 }
1256 
1257 
1261 
1274 /* start documentation of inline functions */
1275 
1290 /* end documentation of inline functions */
1291 /* start documentation of pure virtual functions */
1292 
1333 /* end documentation of pure virtual functions */
1334 /* start documentation of signals */
1335 
1344 /* end documentation of signals */
1345 
1366 QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) :
1367  QObject(plot),
1368  mVisible(true),
1369  mParentPlot(plot),
1370  mParentLayerable(parentLayerable),
1371  mLayer(nullptr),
1372  mAntialiased(true)
1373 {
1374  if (mParentPlot)
1375  {
1376  if (targetLayer.isEmpty())
1378  else if (!setLayer(targetLayer))
1379  qDebug() << Q_FUNC_INFO << "setting QCPlayerable initial layer to" << targetLayer << "failed.";
1380  }
1381 }
1382 
1384 {
1385  if (mLayer)
1386  {
1387  mLayer->removeChild(this);
1388  mLayer = nullptr;
1389  }
1390 }
1391 
1398 {
1399  mVisible = on;
1400 }
1401 
1412 {
1413  return moveToLayer(layer, false);
1414 }
1415 
1421 bool QCPLayerable::setLayer(const QString &layerName)
1422 {
1423  if (!mParentPlot)
1424  {
1425  qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
1426  return false;
1427  }
1428  if (QCPLayer *layer = mParentPlot->layer(layerName))
1429  {
1430  return setLayer(layer);
1431  } else
1432  {
1433  qDebug() << Q_FUNC_INFO << "there is no layer with name" << layerName;
1434  return false;
1435  }
1436 }
1437 
1445 {
1446  mAntialiased = enabled;
1447 }
1448 
1460 {
1461  return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility());
1462 }
1463 
1503 double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
1504 {
1505  Q_UNUSED(pos)
1506  Q_UNUSED(onlySelectable)
1507  Q_UNUSED(details)
1508  return -1.0;
1509 }
1510 
1529 {
1530  if (mParentPlot)
1531  {
1532  qDebug() << Q_FUNC_INFO << "called with mParentPlot already initialized";
1533  return;
1534  }
1535 
1536  if (!parentPlot)
1537  qDebug() << Q_FUNC_INFO << "called with parentPlot zero";
1538 
1541 }
1542 
1555 {
1557 }
1558 
1567 bool QCPLayerable::moveToLayer(QCPLayer *layer, bool prepend)
1568 {
1569  if (layer && !mParentPlot)
1570  {
1571  qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set";
1572  return false;
1573  }
1574  if (layer && layer->parentPlot() != mParentPlot)
1575  {
1576  qDebug() << Q_FUNC_INFO << "layer" << layer->name() << "is not in same QCustomPlot as this layerable";
1577  return false;
1578  }
1579 
1580  QCPLayer *oldLayer = mLayer;
1581  if (mLayer)
1582  mLayer->removeChild(this);
1583  mLayer = layer;
1584  if (mLayer)
1585  mLayer->addChild(this, prepend);
1586  if (mLayer != oldLayer)
1587  emit layerChanged(mLayer);
1588  return true;
1589 }
1590 
1598 void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const
1599 {
1600  if (mParentPlot && mParentPlot->notAntialiasedElements().testFlag(overrideElement))
1601  painter->setAntialiasing(false);
1602  else if (mParentPlot && mParentPlot->antialiasedElements().testFlag(overrideElement))
1603  painter->setAntialiasing(true);
1604  else
1605  painter->setAntialiasing(localAntialiased);
1606 }
1607 
1625 {
1626  Q_UNUSED(parentPlot)
1627 }
1628 
1641 {
1642  return QCP::iSelectOther;
1643 }
1644 
1655 {
1656  if (mParentPlot)
1657  return mParentPlot->viewport();
1658  else
1659  return {};
1660 }
1661 
1690 void QCPLayerable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
1691 {
1692  Q_UNUSED(event)
1693  Q_UNUSED(additive)
1694  Q_UNUSED(details)
1695  Q_UNUSED(selectionStateChanged)
1696 }
1697 
1710 void QCPLayerable::deselectEvent(bool *selectionStateChanged)
1711 {
1712  Q_UNUSED(selectionStateChanged)
1713 }
1714 
1740 void QCPLayerable::mousePressEvent(QMouseEvent *event, const QVariant &details)
1741 {
1742  Q_UNUSED(details)
1743  event->ignore();
1744 }
1745 
1758 void QCPLayerable::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
1759 {
1760  Q_UNUSED(startPos)
1761  event->ignore();
1762 }
1763 
1776 void QCPLayerable::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
1777 {
1778  Q_UNUSED(startPos)
1779  event->ignore();
1780 }
1781 
1808 void QCPLayerable::mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details)
1809 {
1810  Q_UNUSED(details)
1811  event->ignore();
1812 }
1813 
1831 void QCPLayerable::wheelEvent(QWheelEvent *event)
1832 {
1833  event->ignore();
1834 }
1835 /* end of 'src/layer.cpp' */
1836 
1837 
1838 /* including file 'src/axis/range.cpp' */
1839 /* modified 2021-03-29T02:30:44, size 12221 */
1840 
1844 
1853 /* start of documentation of inline functions */
1854 
1896 /* end of documentation of inline functions */
1897 
1909 const double QCPRange::minRange = 1e-280;
1910 
1922 const double QCPRange::maxRange = 1e250;
1923 
1928  lower(0),
1929  upper(0)
1930 {
1931 }
1932 
1940 QCPRange::QCPRange(double lower, double upper) :
1941  lower(lower),
1942  upper(upper)
1943 {
1944  normalize();
1945 }
1946 
1959 void QCPRange::expand(const QCPRange &otherRange)
1960 {
1961  if (lower > otherRange.lower || qIsNaN(lower))
1962  lower = otherRange.lower;
1963  if (upper < otherRange.upper || qIsNaN(upper))
1964  upper = otherRange.upper;
1965 }
1966 
1979 void QCPRange::expand(double includeCoord)
1980 {
1981  if (lower > includeCoord || qIsNaN(lower))
1982  lower = includeCoord;
1983  if (upper < includeCoord || qIsNaN(upper))
1984  upper = includeCoord;
1985 }
1986 
1987 
1998 QCPRange QCPRange::expanded(const QCPRange &otherRange) const
1999 {
2000  QCPRange result = *this;
2001  result.expand(otherRange);
2002  return result;
2003 }
2004 
2015 QCPRange QCPRange::expanded(double includeCoord) const
2016 {
2017  QCPRange result = *this;
2018  result.expand(includeCoord);
2019  return result;
2020 }
2021 
2030 QCPRange QCPRange::bounded(double lowerBound, double upperBound) const
2031 {
2032  if (lowerBound > upperBound)
2033  qSwap(lowerBound, upperBound);
2034 
2035  QCPRange result(lower, upper);
2036  if (result.lower < lowerBound)
2037  {
2038  result.lower = lowerBound;
2039  result.upper = lowerBound + size();
2040  if (result.upper > upperBound || qFuzzyCompare(size(), upperBound-lowerBound))
2041  result.upper = upperBound;
2042  } else if (result.upper > upperBound)
2043  {
2044  result.upper = upperBound;
2045  result.lower = upperBound - size();
2046  if (result.lower < lowerBound || qFuzzyCompare(size(), upperBound-lowerBound))
2047  result.lower = lowerBound;
2048  }
2049 
2050  return result;
2051 }
2052 
2066 {
2067  double rangeFac = 1e-3;
2068  QCPRange sanitizedRange(lower, upper);
2069  sanitizedRange.normalize();
2070  // can't have range spanning negative and positive values in log plot, so change range to fix it
2071  //if (qFuzzyCompare(sanitizedRange.lower+1, 1) && !qFuzzyCompare(sanitizedRange.upper+1, 1))
2072  if (sanitizedRange.lower == 0.0 && sanitizedRange.upper != 0.0)
2073  {
2074  // case lower is 0
2075  if (rangeFac < sanitizedRange.upper*rangeFac)
2076  sanitizedRange.lower = rangeFac;
2077  else
2078  sanitizedRange.lower = sanitizedRange.upper*rangeFac;
2079  } //else if (!qFuzzyCompare(lower+1, 1) && qFuzzyCompare(upper+1, 1))
2080  else if (sanitizedRange.lower != 0.0 && sanitizedRange.upper == 0.0)
2081  {
2082  // case upper is 0
2083  if (-rangeFac > sanitizedRange.lower*rangeFac)
2084  sanitizedRange.upper = -rangeFac;
2085  else
2086  sanitizedRange.upper = sanitizedRange.lower*rangeFac;
2087  } else if (sanitizedRange.lower < 0 && sanitizedRange.upper > 0)
2088  {
2089  // find out whether negative or positive interval is wider to decide which sign domain will be chosen
2090  if (-sanitizedRange.lower > sanitizedRange.upper)
2091  {
2092  // negative is wider, do same as in case upper is 0
2093  if (-rangeFac > sanitizedRange.lower*rangeFac)
2094  sanitizedRange.upper = -rangeFac;
2095  else
2096  sanitizedRange.upper = sanitizedRange.lower*rangeFac;
2097  } else
2098  {
2099  // positive is wider, do same as in case lower is 0
2100  if (rangeFac < sanitizedRange.upper*rangeFac)
2101  sanitizedRange.lower = rangeFac;
2102  else
2103  sanitizedRange.lower = sanitizedRange.upper*rangeFac;
2104  }
2105  }
2106  // due to normalization, case lower>0 && upper<0 should never occur, because that implies upper<lower
2107  return sanitizedRange;
2108 }
2109 
2115 {
2116  QCPRange sanitizedRange(lower, upper);
2117  sanitizedRange.normalize();
2118  return sanitizedRange;
2119 }
2120 
2129 bool QCPRange::validRange(double lower, double upper)
2130 {
2131  return (lower > -maxRange &&
2132  upper < maxRange &&
2133  qAbs(lower-upper) > minRange &&
2134  qAbs(lower-upper) < maxRange &&
2135  !(lower > 0 && qIsInf(upper/lower)) &&
2136  !(upper < 0 && qIsInf(lower/upper)));
2137 }
2138 
2148 bool QCPRange::validRange(const QCPRange &range)
2149 {
2150  return (range.lower > -maxRange &&
2151  range.upper < maxRange &&
2152  qAbs(range.lower-range.upper) > minRange &&
2153  qAbs(range.lower-range.upper) < maxRange &&
2154  !(range.lower > 0 && qIsInf(range.upper/range.lower)) &&
2155  !(range.upper < 0 && qIsInf(range.lower/range.upper)));
2156 }
2157 /* end of 'src/axis/range.cpp' */
2158 
2159 
2160 /* including file 'src/selection.cpp' */
2161 /* modified 2021-03-29T02:30:44, size 21837 */
2162 
2166 
2192 /* start documentation of inline functions */
2193 
2252 /* end documentation of inline functions */
2253 
2258  mBegin(0),
2259  mEnd(0)
2260 {
2261 }
2262 
2268 QCPDataRange::QCPDataRange(int begin, int end) :
2269  mBegin(begin),
2270  mEnd(end)
2271 {
2272 }
2273 
2284 {
2285  QCPDataRange result(intersection(other));
2286  if (result.isEmpty()) // no intersection, preserve respective bounding side of otherRange as both begin and end of return value
2287  {
2288  if (mEnd <= other.mBegin)
2289  result = QCPDataRange(other.mBegin, other.mBegin);
2290  else
2291  result = QCPDataRange(other.mEnd, other.mEnd);
2292  }
2293  return result;
2294 }
2295 
2300 {
2301  return {qMin(mBegin, other.mBegin), qMax(mEnd, other.mEnd)};
2302 }
2303 
2315 {
2316  QCPDataRange result(qMax(mBegin, other.mBegin), qMin(mEnd, other.mEnd));
2317  if (result.isValid())
2318  return result;
2319  else
2320  return {};
2321 }
2322 
2328 bool QCPDataRange::intersects(const QCPDataRange &other) const
2329 {
2330  return !( (mBegin > other.mBegin && mBegin >= other.mEnd) ||
2331  (mEnd <= other.mBegin && mEnd < other.mEnd) );
2332 }
2333 
2339 bool QCPDataRange::contains(const QCPDataRange &other) const
2340 {
2341  return mBegin <= other.mBegin && mEnd >= other.mEnd;
2342 }
2343 
2344 
2345 
2349 
2383 /* start documentation of inline functions */
2384 
2410 /* end documentation of inline functions */
2411 
2416 {
2417 }
2418 
2423 {
2424  mDataRanges.append(range);
2425 }
2426 
2435 {
2436  if (mDataRanges.size() != other.mDataRanges.size())
2437  return false;
2438  for (int i=0; i<mDataRanges.size(); ++i)
2439  {
2440  if (mDataRanges.at(i) != other.mDataRanges.at(i))
2441  return false;
2442  }
2443  return true;
2444 }
2445 
2451 {
2452  mDataRanges << other.mDataRanges;
2453  simplify();
2454  return *this;
2455 }
2456 
2462 {
2463  addDataRange(other);
2464  return *this;
2465 }
2466 
2471 {
2472  for (int i=0; i<other.dataRangeCount(); ++i)
2473  *this -= other.dataRange(i);
2474 
2475  return *this;
2476 }
2477 
2482 {
2483  if (other.isEmpty() || isEmpty())
2484  return *this;
2485 
2486  simplify();
2487  int i=0;
2488  while (i < mDataRanges.size())
2489  {
2490  const int thisBegin = mDataRanges.at(i).begin();
2491  const int thisEnd = mDataRanges.at(i).end();
2492  if (thisBegin >= other.end())
2493  break; // since data ranges are sorted after the simplify() call, no ranges which contain other will come after this
2494 
2495  if (thisEnd > other.begin()) // ranges which don't fulfill this are entirely before other and can be ignored
2496  {
2497  if (thisBegin >= other.begin()) // range leading segment is encompassed
2498  {
2499  if (thisEnd <= other.end()) // range fully encompassed, remove completely
2500  {
2501  mDataRanges.removeAt(i);
2502  continue;
2503  } else // only leading segment is encompassed, trim accordingly
2504  mDataRanges[i].setBegin(other.end());
2505  } else // leading segment is not encompassed
2506  {
2507  if (thisEnd <= other.end()) // only trailing segment is encompassed, trim accordingly
2508  {
2509  mDataRanges[i].setEnd(other.begin());
2510  } else // other lies inside this range, so split range
2511  {
2512  mDataRanges[i].setEnd(other.begin());
2513  mDataRanges.insert(i+1, QCPDataRange(other.end(), thisEnd));
2514  break; // since data ranges are sorted (and don't overlap) after simplify() call, we're done here
2515  }
2516  }
2517  }
2518  ++i;
2519  }
2520 
2521  return *this;
2522 }
2523 
2529 {
2530  int result = 0;
2531  foreach (QCPDataRange dataRange, mDataRanges)
2532  result += dataRange.length();
2533  return result;
2534 }
2535 
2545 {
2546  if (index >= 0 && index < mDataRanges.size())
2547  {
2548  return mDataRanges.at(index);
2549  } else
2550  {
2551  qDebug() << Q_FUNC_INFO << "index out of range:" << index;
2552  return {};
2553  }
2554 }
2555 
2561 {
2562  if (isEmpty())
2563  return {};
2564  else
2565  return {mDataRanges.first().begin(), mDataRanges.last().end()};
2566 }
2567 
2574 void QCPDataSelection::addDataRange(const QCPDataRange &dataRange, bool simplify)
2575 {
2576  mDataRanges.append(dataRange);
2577  if (simplify)
2578  this->simplify();
2579 }
2580 
2587 {
2588  mDataRanges.clear();
2589 }
2590 
2601 {
2602  // remove any empty ranges:
2603  for (int i=mDataRanges.size()-1; i>=0; --i)
2604  {
2605  if (mDataRanges.at(i).isEmpty())
2606  mDataRanges.removeAt(i);
2607  }
2608  if (mDataRanges.isEmpty())
2609  return;
2610 
2611  // sort ranges by starting value, ascending:
2612  std::sort(mDataRanges.begin(), mDataRanges.end(), lessThanDataRangeBegin);
2613 
2614  // join overlapping/contiguous ranges:
2615  int i = 1;
2616  while (i < mDataRanges.size())
2617  {
2618  if (mDataRanges.at(i-1).end() >= mDataRanges.at(i).begin()) // range i overlaps/joins with i-1, so expand range i-1 appropriately and remove range i from list
2619  {
2620  mDataRanges[i-1].setEnd(qMax(mDataRanges.at(i-1).end(), mDataRanges.at(i).end()));
2621  mDataRanges.removeAt(i);
2622  } else
2623  ++i;
2624  }
2625 }
2626 
2638 {
2639  simplify();
2640  switch (type)
2641  {
2642  case QCP::stNone:
2643  {
2644  mDataRanges.clear();
2645  break;
2646  }
2647  case QCP::stWhole:
2648  {
2649  // whole selection isn't defined by data range, so don't change anything (is handled in plottable methods)
2650  break;
2651  }
2652  case QCP::stSingleData:
2653  {
2654  // reduce all data ranges to the single first data point:
2655  if (!mDataRanges.isEmpty())
2656  {
2657  if (mDataRanges.size() > 1)
2658  mDataRanges = QList<QCPDataRange>() << mDataRanges.first();
2659  if (mDataRanges.first().length() > 1)
2660  mDataRanges.first().setEnd(mDataRanges.first().begin()+1);
2661  }
2662  break;
2663  }
2664  case QCP::stDataRange:
2665  {
2666  if (!isEmpty())
2667  mDataRanges = QList<QCPDataRange>() << span();
2668  break;
2669  }
2671  {
2672  // this is the selection type that allows all concievable combinations of ranges, so do nothing
2673  break;
2674  }
2675  }
2676 }
2677 
2685 {
2686  if (other.isEmpty()) return false;
2687 
2688  int otherIndex = 0;
2689  int thisIndex = 0;
2690  while (thisIndex < mDataRanges.size() && otherIndex < other.mDataRanges.size())
2691  {
2692  if (mDataRanges.at(thisIndex).contains(other.mDataRanges.at(otherIndex)))
2693  ++otherIndex;
2694  else
2695  ++thisIndex;
2696  }
2697  return thisIndex < mDataRanges.size(); // if thisIndex ran all the way to the end to find a containing range for the current otherIndex, other is not contained in this
2698 }
2699 
2709 {
2710  QCPDataSelection result;
2711  foreach (QCPDataRange dataRange, mDataRanges)
2712  result.addDataRange(dataRange.intersection(other), false);
2713  result.simplify();
2714  return result;
2715 }
2716 
2722 {
2723  QCPDataSelection result;
2724  for (int i=0; i<other.dataRangeCount(); ++i)
2725  result += intersection(other.dataRange(i));
2726  result.simplify();
2727  return result;
2728 }
2729 
2740 {
2741  if (isEmpty())
2742  return QCPDataSelection(outerRange);
2743  QCPDataRange fullRange = outerRange.expanded(span());
2744 
2745  QCPDataSelection result;
2746  // first unselected segment:
2747  if (mDataRanges.first().begin() != fullRange.begin())
2748  result.addDataRange(QCPDataRange(fullRange.begin(), mDataRanges.first().begin()), false);
2749  // intermediate unselected segments:
2750  for (int i=1; i<mDataRanges.size(); ++i)
2751  result.addDataRange(QCPDataRange(mDataRanges.at(i-1).end(), mDataRanges.at(i).begin()), false);
2752  // last unselected segment:
2753  if (mDataRanges.last().end() != fullRange.end())
2754  result.addDataRange(QCPDataRange(mDataRanges.last().end(), fullRange.end()), false);
2755  result.simplify();
2756  return result;
2757 }
2758 /* end of 'src/selection.cpp' */
2759 
2760 
2761 /* including file 'src/selectionrect.cpp' */
2762 /* modified 2021-03-29T02:30:44, size 9215 */
2763 
2767 
2790 /* start of documentation of inline functions */
2791 
2800 /* end of documentation of inline functions */
2801 /* start documentation of signals */
2802 
2839 /* end documentation of signals */
2840 
2847  QCPLayerable(parentPlot),
2848  mPen(QBrush(Qt::gray), 0, Qt::DashLine),
2849  mBrush(Qt::NoBrush),
2850  mActive(false)
2851 {
2852 }
2853 
2855 {
2856  cancel();
2857 }
2858 
2864 {
2865  if (axis)
2866  {
2867  if (axis->orientation() == Qt::Horizontal)
2868  return {axis->pixelToCoord(mRect.left()), axis->pixelToCoord(mRect.left()+mRect.width())};
2869  else
2870  return {axis->pixelToCoord(mRect.top()+mRect.height()), axis->pixelToCoord(mRect.top())};
2871  } else
2872  {
2873  qDebug() << Q_FUNC_INFO << "called with axis zero";
2874  return {};
2875  }
2876 }
2877 
2883 void QCPSelectionRect::setPen(const QPen &pen)
2884 {
2885  mPen = pen;
2886 }
2887 
2894 void QCPSelectionRect::setBrush(const QBrush &brush)
2895 {
2896  mBrush = brush;
2897 }
2898 
2904 {
2905  if (mActive)
2906  {
2907  mActive = false;
2908  emit canceled(mRect, nullptr);
2909  }
2910 }
2911 
2918 void QCPSelectionRect::startSelection(QMouseEvent *event)
2919 {
2920  mActive = true;
2921  mRect = QRect(event->pos(), event->pos());
2922  emit started(event);
2923 }
2924 
2931 void QCPSelectionRect::moveSelection(QMouseEvent *event)
2932 {
2933  mRect.setBottomRight(event->pos());
2934  emit changed(mRect, event);
2935  layer()->replot();
2936 }
2937 
2944 void QCPSelectionRect::endSelection(QMouseEvent *event)
2945 {
2946  mRect.setBottomRight(event->pos());
2947  mActive = false;
2948  emit accepted(mRect, event);
2949 }
2950 
2957 void QCPSelectionRect::keyPressEvent(QKeyEvent *event)
2958 {
2959  if (event->key() == Qt::Key_Escape && mActive)
2960  {
2961  mActive = false;
2962  emit canceled(mRect, event);
2963  }
2964 }
2965 
2966 /* inherits documentation from base class */
2968 {
2970 }
2971 
2979 {
2980  if (mActive)
2981  {
2982  painter->setPen(mPen);
2983  painter->setBrush(mBrush);
2984  painter->drawRect(mRect);
2985  }
2986 }
2987 /* end of 'src/selectionrect.cpp' */
2988 
2989 
2990 /* including file 'src/layout.cpp' */
2991 /* modified 2021-03-29T02:30:44, size 78863 */
2992 
2996 
3028 /* start documentation of inline functions */
3029 
3036 /* end documentation of inline functions */
3037 
3042  QObject(parentPlot),
3043  mParentPlot(parentPlot)
3044 {
3045  mChildren.insert(QCP::msLeft, QList<QCPLayoutElement*>());
3046  mChildren.insert(QCP::msRight, QList<QCPLayoutElement*>());
3047  mChildren.insert(QCP::msTop, QList<QCPLayoutElement*>());
3048  mChildren.insert(QCP::msBottom, QList<QCPLayoutElement*>());
3049 }
3050 
3052 {
3053  clear();
3054 }
3055 
3061 {
3062  QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
3063  while (it.hasNext())
3064  {
3065  it.next();
3066  if (!it.value().isEmpty())
3067  return false;
3068  }
3069  return true;
3070 }
3071 
3077 {
3078  // make all children remove themselves from this margin group:
3079  QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(mChildren);
3080  while (it.hasNext())
3081  {
3082  it.next();
3083  const QList<QCPLayoutElement*> elements = it.value();
3084  for (int i=elements.size()-1; i>=0; --i)
3085  elements.at(i)->setMarginGroup(it.key(), nullptr); // removes itself from mChildren via removeChild
3086  }
3087 }
3088 
3100 {
3101  // query all automatic margins of the layout elements in this margin group side and find maximum:
3102  int result = 0;
3103  foreach (QCPLayoutElement *el, mChildren.value(side))
3104  {
3105  if (!el->autoMargins().testFlag(side))
3106  continue;
3107  int m = qMax(el->calculateAutoMargin(side), QCP::getMarginValue(el->minimumMargins(), side));
3108  if (m > result)
3109  result = m;
3110  }
3111  return result;
3112 }
3113 
3121 {
3122  if (!mChildren[side].contains(element))
3123  mChildren[side].append(element);
3124  else
3125  qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast<quintptr>(element);
3126 }
3127 
3135 {
3136  if (!mChildren[side].removeOne(element))
3137  qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast<quintptr>(element);
3138 }
3139 
3140 
3144 
3171 /* start documentation of inline functions */
3172 
3202 /* end documentation of inline functions */
3203 
3208  QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout)
3209  mParentLayout(nullptr),
3210  mMinimumSize(),
3211  mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX),
3212  mSizeConstraintRect(scrInnerRect),
3213  mRect(0, 0, 0, 0),
3214  mOuterRect(0, 0, 0, 0),
3215  mMargins(0, 0, 0, 0),
3216  mMinimumMargins(0, 0, 0, 0),
3217  mAutoMargins(QCP::msAll)
3218 {
3219 }
3220 
3222 {
3223  setMarginGroup(QCP::msAll, nullptr); // unregister at margin groups, if there are any
3224  // unregister at layout:
3225  if (qobject_cast<QCPLayout*>(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor
3226  mParentLayout->take(this);
3227 }
3228 
3240 void QCPLayoutElement::setOuterRect(const QRect &rect)
3241 {
3242  if (mOuterRect != rect)
3243  {
3244  mOuterRect = rect;
3245  mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
3246  }
3247 }
3248 
3260 void QCPLayoutElement::setMargins(const QMargins &margins)
3261 {
3262  if (mMargins != margins)
3263  {
3264  mMargins = margins;
3265  mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom());
3266  }
3267 }
3268 
3278 void QCPLayoutElement::setMinimumMargins(const QMargins &margins)
3279 {
3280  if (mMinimumMargins != margins)
3281  {
3283  }
3284 }
3285 
3296 void QCPLayoutElement::setAutoMargins(QCP::MarginSides sides)
3297 {
3298  mAutoMargins = sides;
3299 }
3300 
3313 void QCPLayoutElement::setMinimumSize(const QSize &size)
3314 {
3315  if (mMinimumSize != size)
3316  {
3317  mMinimumSize = size;
3318  if (mParentLayout)
3320  }
3321 }
3322 
3330 void QCPLayoutElement::setMinimumSize(int width, int height)
3331 {
3332  setMinimumSize(QSize(width, height));
3333 }
3334 
3342 void QCPLayoutElement::setMaximumSize(const QSize &size)
3343 {
3344  if (mMaximumSize != size)
3345  {
3346  mMaximumSize = size;
3347  if (mParentLayout)
3349  }
3350 }
3351 
3359 void QCPLayoutElement::setMaximumSize(int width, int height)
3360 {
3361  setMaximumSize(QSize(width, height));
3362 }
3363 
3374 {
3375  if (mSizeConstraintRect != constraintRect)
3376  {
3377  mSizeConstraintRect = constraintRect;
3378  if (mParentLayout)
3380  }
3381 }
3382 
3396 void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group)
3397 {
3398  QVector<QCP::MarginSide> sideVector;
3399  if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft);
3400  if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight);
3401  if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop);
3402  if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom);
3403 
3404  foreach (QCP::MarginSide side, sideVector)
3405  {
3406  if (marginGroup(side) != group)
3407  {
3408  QCPMarginGroup *oldGroup = marginGroup(side);
3409  if (oldGroup) // unregister at old group
3410  oldGroup->removeChild(side, this);
3411 
3412  if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there
3413  {
3414  mMarginGroups.remove(side);
3415  } else // setting to a new group
3416  {
3417  mMarginGroups[side] = group;
3418  group->addChild(side, this);
3419  }
3420  }
3421  }
3422 }
3423 
3437 {
3438  if (phase == upMargins)
3439  {
3440  if (mAutoMargins != QCP::msNone)
3441  {
3442  // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group:
3443  QMargins newMargins = mMargins;
3444  const QList<QCP::MarginSide> allMarginSides = QList<QCP::MarginSide>() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom;
3445  foreach (QCP::MarginSide side, allMarginSides)
3446  {
3447  if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically
3448  {
3449  if (mMarginGroups.contains(side))
3450  QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group
3451  else
3452  QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly
3453  // apply minimum margin restrictions:
3454  if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side))
3455  QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side));
3456  }
3457  }
3458  setMargins(newMargins);
3459  }
3460  }
3461 }
3462 
3478 {
3479  return {mMargins.left()+mMargins.right(), mMargins.top()+mMargins.bottom()};
3480 }
3481 
3497 {
3498  return {QWIDGETSIZE_MAX, QWIDGETSIZE_MAX};
3499 }
3500 
3508 QList<QCPLayoutElement*> QCPLayoutElement::elements(bool recursive) const
3509 {
3510  Q_UNUSED(recursive)
3511  return QList<QCPLayoutElement*>();
3512 }
3513 
3525 double QCPLayoutElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
3526 {
3527  Q_UNUSED(details)
3528 
3529  if (onlySelectable)
3530  return -1;
3531 
3532  if (QRectF(mOuterRect).contains(pos))
3533  {
3534  if (mParentPlot)
3535  return mParentPlot->selectionTolerance()*0.99;
3536  else
3537  {
3538  qDebug() << Q_FUNC_INFO << "parent plot not defined";
3539  return -1;
3540  }
3541  } else
3542  return -1;
3543 }
3544 
3551 {
3552  foreach (QCPLayoutElement *el, elements(false))
3553  {
3554  if (!el->parentPlot())
3556  }
3557 }
3558 
3569 {
3571 }
3572 
3585 {
3586 }
3587 
3591 
3615 /* start documentation of pure virtual functions */
3616 
3660 /* end documentation of pure virtual functions */
3661 
3667 {
3668 }
3669 
3680 {
3681  QCPLayoutElement::update(phase);
3682 
3683  // set child element rects according to layout:
3684  if (phase == upLayout)
3685  updateLayout();
3686 
3687  // propagate update call to child elements:
3688  const int elCount = elementCount();
3689  for (int i=0; i<elCount; ++i)
3690  {
3691  if (QCPLayoutElement *el = elementAt(i))
3692  el->update(phase);
3693  }
3694 }
3695 
3696 /* inherits documentation from base class */
3697 QList<QCPLayoutElement*> QCPLayout::elements(bool recursive) const
3698 {
3699  const int c = elementCount();
3700  QList<QCPLayoutElement*> result;
3701 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
3702  result.reserve(c);
3703 #endif
3704  for (int i=0; i<c; ++i)
3705  result.append(elementAt(i));
3706  if (recursive)
3707  {
3708  for (int i=0; i<c; ++i)
3709  {
3710  if (result.at(i))
3711  result << result.at(i)->elements(recursive);
3712  }
3713  }
3714  return result;
3715 }
3716 
3725 {
3726 }
3727 
3739 bool QCPLayout::removeAt(int index)
3740 {
3741  if (QCPLayoutElement *el = takeAt(index))
3742  {
3743  delete el;
3744  return true;
3745  } else
3746  return false;
3747 }
3748 
3761 {
3762  if (take(element))
3763  {
3764  delete element;
3765  return true;
3766  } else
3767  return false;
3768 }
3769 
3777 {
3778  for (int i=elementCount()-1; i>=0; --i)
3779  {
3780  if (elementAt(i))
3781  removeAt(i);
3782  }
3783  simplify();
3784 }
3785 
3795 {
3796  if (QWidget *w = qobject_cast<QWidget*>(parent()))
3797  w->updateGeometry();
3798  else if (QCPLayout *l = qobject_cast<QCPLayout*>(parent()))
3799  l->sizeConstraintsChanged();
3800 }
3801 
3815 {
3816 }
3817 
3818 
3832 {
3833  if (el)
3834  {
3835  el->mParentLayout = this;
3836  el->setParentLayerable(this);
3837  el->setParent(this);
3838  if (!el->parentPlot())
3840  el->layoutChanged();
3841  } else
3842  qDebug() << Q_FUNC_INFO << "Null element passed";
3843 }
3844 
3856 {
3857  if (el)
3858  {
3859  el->mParentLayout = nullptr;
3860  el->setParentLayerable(nullptr);
3861  el->setParent(mParentPlot);
3862  // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot
3863  } else
3864  qDebug() << Q_FUNC_INFO << "Null element passed";
3865 }
3866 
3896 QVector<int> QCPLayout::getSectionSizes(QVector<int> maxSizes, QVector<int> minSizes, QVector<double> stretchFactors, int totalSize) const
3897 {
3898  if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size())
3899  {
3900  qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors;
3901  return QVector<int>();
3902  }
3903  if (stretchFactors.isEmpty())
3904  return QVector<int>();
3905  int sectionCount = stretchFactors.size();
3906  QVector<double> sectionSizes(sectionCount);
3907  // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections):
3908  int minSizeSum = 0;
3909  for (int i=0; i<sectionCount; ++i)
3910  minSizeSum += minSizes.at(i);
3911  if (totalSize < minSizeSum)
3912  {
3913  // new stretch factors are minimum sizes and minimum sizes are set to zero:
3914  for (int i=0; i<sectionCount; ++i)
3915  {
3916  stretchFactors[i] = minSizes.at(i);
3917  minSizes[i] = 0;
3918  }
3919  }
3920 
3921  QList<int> minimumLockedSections;
3922  QList<int> unfinishedSections;
3923  for (int i=0; i<sectionCount; ++i)
3924  unfinishedSections.append(i);
3925  double freeSize = totalSize;
3926 
3927  int outerIterations = 0;
3928  while (!unfinishedSections.isEmpty() && outerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
3929  {
3930  ++outerIterations;
3931  int innerIterations = 0;
3932  while (!unfinishedSections.isEmpty() && innerIterations < sectionCount*2) // the iteration check ist just a failsafe in case something really strange happens
3933  {
3934  ++innerIterations;
3935  // find section that hits its maximum next:
3936  int nextId = -1;
3937  double nextMax = 1e12;
3938  foreach (int secId, unfinishedSections)
3939  {
3940  double hitsMaxAt = (maxSizes.at(secId)-sectionSizes.at(secId))/stretchFactors.at(secId);
3941  if (hitsMaxAt < nextMax)
3942  {
3943  nextMax = hitsMaxAt;
3944  nextId = secId;
3945  }
3946  }
3947  // check if that maximum is actually within the bounds of the total size (i.e. can we stretch all remaining sections so far that the found section
3948  // actually hits its maximum, without exceeding the total size when we add up all sections)
3949  double stretchFactorSum = 0;
3950  foreach (int secId, unfinishedSections)
3951  stretchFactorSum += stretchFactors.at(secId);
3952  double nextMaxLimit = freeSize/stretchFactorSum;
3953  if (nextMax < nextMaxLimit) // next maximum is actually hit, move forward to that point and fix the size of that section
3954  {
3955  foreach (int secId, unfinishedSections)
3956  {
3957  sectionSizes[secId] += nextMax*stretchFactors.at(secId); // increment all sections
3958  freeSize -= nextMax*stretchFactors.at(secId);
3959  }
3960  unfinishedSections.removeOne(nextId); // exclude the section that is now at maximum from further changes
3961  } else // next maximum isn't hit, just distribute rest of free space on remaining sections
3962  {
3963  foreach (int secId, unfinishedSections)
3964  sectionSizes[secId] += nextMaxLimit*stretchFactors.at(secId); // increment all sections
3965  unfinishedSections.clear();
3966  }
3967  }
3968  if (innerIterations == sectionCount*2)
3969  qDebug() << Q_FUNC_INFO << "Exceeded maximum expected inner iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
3970 
3971  // now check whether the resulting section sizes violate minimum restrictions:
3972  bool foundMinimumViolation = false;
3973  for (int i=0; i<sectionSizes.size(); ++i)
3974  {
3975  if (minimumLockedSections.contains(i))
3976  continue;
3977  if (sectionSizes.at(i) < minSizes.at(i)) // section violates minimum
3978  {
3979  sectionSizes[i] = minSizes.at(i); // set it to minimum
3980  foundMinimumViolation = true; // make sure we repeat the whole optimization process
3981  minimumLockedSections.append(i);
3982  }
3983  }
3984  if (foundMinimumViolation)
3985  {
3986  freeSize = totalSize;
3987  for (int i=0; i<sectionCount; ++i)
3988  {
3989  if (!minimumLockedSections.contains(i)) // only put sections that haven't hit their minimum back into the pool
3990  unfinishedSections.append(i);
3991  else
3992  freeSize -= sectionSizes.at(i); // remove size of minimum locked sections from available space in next round
3993  }
3994  // reset all section sizes to zero that are in unfinished sections (all others have been set to their minimum):
3995  foreach (int secId, unfinishedSections)
3996  sectionSizes[secId] = 0;
3997  }
3998  }
3999  if (outerIterations == sectionCount*2)
4000  qDebug() << Q_FUNC_INFO << "Exceeded maximum expected outer iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
4001 
4002  QVector<int> result(sectionCount);
4003  for (int i=0; i<sectionCount; ++i)
4004  result[i] = qRound(sectionSizes.at(i));
4005  return result;
4006 }
4007 
4021 {
4022  QSize minOuterHint = el->minimumOuterSizeHint();
4023  QSize minOuter = el->minimumSize(); // depending on sizeConstraitRect this might be with respect to inner rect, so possibly add margins in next four lines (preserving unset minimum of 0)
4024  if (minOuter.width() > 0 && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect)
4025  minOuter.rwidth() += el->margins().left() + el->margins().right();
4026  if (minOuter.height() > 0 && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect)
4027  minOuter.rheight() += el->margins().top() + el->margins().bottom();
4028 
4029  return {minOuter.width() > 0 ? minOuter.width() : minOuterHint.width(),
4030  minOuter.height() > 0 ? minOuter.height() : minOuterHint.height()};
4031 }
4032 
4046 {
4047  QSize maxOuterHint = el->maximumOuterSizeHint();
4048  QSize maxOuter = el->maximumSize(); // depending on sizeConstraitRect this might be with respect to inner rect, so possibly add margins in next four lines (preserving unset maximum of QWIDGETSIZE_MAX)
4049  if (maxOuter.width() < QWIDGETSIZE_MAX && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect)
4050  maxOuter.rwidth() += el->margins().left() + el->margins().right();
4051  if (maxOuter.height() < QWIDGETSIZE_MAX && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect)
4052  maxOuter.rheight() += el->margins().top() + el->margins().bottom();
4053 
4054  return {maxOuter.width() < QWIDGETSIZE_MAX ? maxOuter.width() : maxOuterHint.width(),
4055  maxOuter.height() < QWIDGETSIZE_MAX ? maxOuter.height() : maxOuterHint.height()};
4056 }
4057 
4058 
4062 
4083 /* start documentation of inline functions */
4084 
4099 /* end documentation of inline functions */
4100 
4105  mColumnSpacing(5),
4106  mRowSpacing(5),
4107  mWrap(0),
4108  mFillOrder(foColumnsFirst)
4109 {
4110 }
4111 
4113 {
4114  // clear all child layout elements. This is important because only the specific layouts know how
4115  // to handle removing elements (clear calls virtual removeAt method to do that).
4116  clear();
4117 }
4118 
4127 QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const
4128 {
4129  if (row >= 0 && row < mElements.size())
4130  {
4131  if (column >= 0 && column < mElements.first().size())
4132  {
4133  if (QCPLayoutElement *result = mElements.at(row).at(column))
4134  return result;
4135  else
4136  qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column;
4137  } else
4138  qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column;
4139  } else
4140  qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column;
4141  return nullptr;
4142 }
4143 
4144 
4159 bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element)
4160 {
4161  if (!hasElement(row, column))
4162  {
4163  if (element && element->layout()) // remove from old layout first
4164  element->layout()->take(element);
4165  expandTo(row+1, column+1);
4166  mElements[row][column] = element;
4167  if (element)
4169  return true;
4170  } else
4171  qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column;
4172  return false;
4173 }
4174 
4186 {
4187  int rowIndex = 0;
4188  int colIndex = 0;
4189  if (mFillOrder == foColumnsFirst)
4190  {
4191  while (hasElement(rowIndex, colIndex))
4192  {
4193  ++colIndex;
4194  if (colIndex >= mWrap && mWrap > 0)
4195  {
4196  colIndex = 0;
4197  ++rowIndex;
4198  }
4199  }
4200  } else
4201  {
4202  while (hasElement(rowIndex, colIndex))
4203  {
4204  ++rowIndex;
4205  if (rowIndex >= mWrap && mWrap > 0)
4206  {
4207  rowIndex = 0;
4208  ++colIndex;
4209  }
4210  }
4211  }
4212  return addElement(rowIndex, colIndex, element);
4213 }
4214 
4221 bool QCPLayoutGrid::hasElement(int row, int column)
4222 {
4223  if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount())
4224  return mElements.at(row).at(column);
4225  else
4226  return false;
4227 }
4228 
4241 void QCPLayoutGrid::setColumnStretchFactor(int column, double factor)
4242 {
4243  if (column >= 0 && column < columnCount())
4244  {
4245  if (factor > 0)
4246  mColumnStretchFactors[column] = factor;
4247  else
4248  qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
4249  } else
4250  qDebug() << Q_FUNC_INFO << "Invalid column:" << column;
4251 }
4252 
4265 void QCPLayoutGrid::setColumnStretchFactors(const QList<double> &factors)
4266 {
4267  if (factors.size() == mColumnStretchFactors.size())
4268  {
4269  mColumnStretchFactors = factors;
4270  for (int i=0; i<mColumnStretchFactors.size(); ++i)
4271  {
4272  if (mColumnStretchFactors.at(i) <= 0)
4273  {
4274  qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mColumnStretchFactors.at(i);
4275  mColumnStretchFactors[i] = 1;
4276  }
4277  }
4278  } else
4279  qDebug() << Q_FUNC_INFO << "Column count not equal to passed stretch factor count:" << factors;
4280 }
4281 
4294 void QCPLayoutGrid::setRowStretchFactor(int row, double factor)
4295 {
4296  if (row >= 0 && row < rowCount())
4297  {
4298  if (factor > 0)
4299  mRowStretchFactors[row] = factor;
4300  else
4301  qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor;
4302  } else
4303  qDebug() << Q_FUNC_INFO << "Invalid row:" << row;
4304 }
4305 
4318 void QCPLayoutGrid::setRowStretchFactors(const QList<double> &factors)
4319 {
4320  if (factors.size() == mRowStretchFactors.size())
4321  {
4322  mRowStretchFactors = factors;
4323  for (int i=0; i<mRowStretchFactors.size(); ++i)
4324  {
4325  if (mRowStretchFactors.at(i) <= 0)
4326  {
4327  qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << mRowStretchFactors.at(i);
4328  mRowStretchFactors[i] = 1;
4329  }
4330  }
4331  } else
4332  qDebug() << Q_FUNC_INFO << "Row count not equal to passed stretch factor count:" << factors;
4333 }
4334 
4341 {
4342  mColumnSpacing = pixels;
4343 }
4344 
4351 {
4352  mRowSpacing = pixels;
4353 }
4354 
4372 void QCPLayoutGrid::setWrap(int count)
4373 {
4374  mWrap = qMax(0, count);
4375 }
4376 
4402 void QCPLayoutGrid::setFillOrder(FillOrder order, bool rearrange)
4403 {
4404  // if rearranging, take all elements via linear index of old fill order:
4405  const int elCount = elementCount();
4406  QVector<QCPLayoutElement*> tempElements;
4407  if (rearrange)
4408  {
4409  tempElements.reserve(elCount);
4410  for (int i=0; i<elCount; ++i)
4411  {
4412  if (elementAt(i))
4413  tempElements.append(takeAt(i));
4414  }
4415  simplify();
4416  }
4417  // change fill order as requested:
4418  mFillOrder = order;
4419  // if rearranging, re-insert via linear index according to new fill order:
4420  if (rearrange)
4421  {
4422  foreach (QCPLayoutElement *tempElement, tempElements)
4423  addElement(tempElement);
4424  }
4425 }
4426 
4441 void QCPLayoutGrid::expandTo(int newRowCount, int newColumnCount)
4442 {
4443  // add rows as necessary:
4444  while (rowCount() < newRowCount)
4445  {
4446  mElements.append(QList<QCPLayoutElement*>());
4447  mRowStretchFactors.append(1);
4448  }
4449  // go through rows and expand columns as necessary:
4450  int newColCount = qMax(columnCount(), newColumnCount);
4451  for (int i=0; i<rowCount(); ++i)
4452  {
4453  while (mElements.at(i).size() < newColCount)
4454  mElements[i].append(nullptr);
4455  }
4456  while (mColumnStretchFactors.size() < newColCount)
4457  mColumnStretchFactors.append(1);
4458 }
4459 
4466 void QCPLayoutGrid::insertRow(int newIndex)
4467 {
4468  if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
4469  {
4470  expandTo(1, 1);
4471  return;
4472  }
4473 
4474  if (newIndex < 0)
4475  newIndex = 0;
4476  if (newIndex > rowCount())
4477  newIndex = rowCount();
4478 
4479  mRowStretchFactors.insert(newIndex, 1);
4480  QList<QCPLayoutElement*> newRow;
4481  for (int col=0; col<columnCount(); ++col)
4482  newRow.append(nullptr);
4483  mElements.insert(newIndex, newRow);
4484 }
4485 
4494 {
4495  if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell
4496  {
4497  expandTo(1, 1);
4498  return;
4499  }
4500 
4501  if (newIndex < 0)
4502  newIndex = 0;
4503  if (newIndex > columnCount())
4504  newIndex = columnCount();
4505 
4506  mColumnStretchFactors.insert(newIndex, 1);
4507  for (int row=0; row<rowCount(); ++row)
4508  mElements[row].insert(newIndex, nullptr);
4509 }
4510 
4524 int QCPLayoutGrid::rowColToIndex(int row, int column) const
4525 {
4526  if (row >= 0 && row < rowCount())
4527  {
4528  if (column >= 0 && column < columnCount())
4529  {
4530  switch (mFillOrder)
4531  {
4532  case foRowsFirst: return column*rowCount() + row;
4533  case foColumnsFirst: return row*columnCount() + column;
4534  }
4535  } else
4536  qDebug() << Q_FUNC_INFO << "row index out of bounds:" << row;
4537  } else
4538  qDebug() << Q_FUNC_INFO << "column index out of bounds:" << column;
4539  return 0;
4540 }
4541 
4557 void QCPLayoutGrid::indexToRowCol(int index, int &row, int &column) const
4558 {
4559  row = -1;
4560  column = -1;
4561  const int nCols = columnCount();
4562  const int nRows = rowCount();
4563  if (nCols == 0 || nRows == 0)
4564  return;
4565  if (index < 0 || index >= elementCount())
4566  {
4567  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
4568  return;
4569  }
4570 
4571  switch (mFillOrder)
4572  {
4573  case foRowsFirst:
4574  {
4575  column = index / nRows;
4576  row = index % nRows;
4577  break;
4578  }
4579  case foColumnsFirst:
4580  {
4581  row = index / nCols;
4582  column = index % nCols;
4583  break;
4584  }
4585  }
4586 }
4587 
4588 /* inherits documentation from base class */
4590 {
4591  QVector<int> minColWidths, minRowHeights, maxColWidths, maxRowHeights;
4592  getMinimumRowColSizes(&minColWidths, &minRowHeights);
4593  getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
4594 
4595  int totalRowSpacing = (rowCount()-1) * mRowSpacing;
4596  int totalColSpacing = (columnCount()-1) * mColumnSpacing;
4597  QVector<int> colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing);
4598  QVector<int> rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing);
4599 
4600  // go through cells and set rects accordingly:
4601  int yOffset = mRect.top();
4602  for (int row=0; row<rowCount(); ++row)
4603  {
4604  if (row > 0)
4605  yOffset += rowHeights.at(row-1)+mRowSpacing;
4606  int xOffset = mRect.left();
4607  for (int col=0; col<columnCount(); ++col)
4608  {
4609  if (col > 0)
4610  xOffset += colWidths.at(col-1)+mColumnSpacing;
4611  if (mElements.at(row).at(col))
4612  mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row)));
4613  }
4614  }
4615 }
4616 
4626 {
4627  if (index >= 0 && index < elementCount())
4628  {
4629  int row, col;
4630  indexToRowCol(index, row, col);
4631  return mElements.at(row).at(col);
4632  } else
4633  return nullptr;
4634 }
4635 
4645 {
4646  if (QCPLayoutElement *el = elementAt(index))
4647  {
4648  releaseElement(el);
4649  int row, col;
4650  indexToRowCol(index, row, col);
4651  mElements[row][col] = nullptr;
4652  return el;
4653  } else
4654  {
4655  qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
4656  return nullptr;
4657  }
4658 }
4659 
4660 /* inherits documentation from base class */
4662 {
4663  if (element)
4664  {
4665  for (int i=0; i<elementCount(); ++i)
4666  {
4667  if (elementAt(i) == element)
4668  {
4669  takeAt(i);
4670  return true;
4671  }
4672  }
4673  qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
4674  } else
4675  qDebug() << Q_FUNC_INFO << "Can't take nullptr element";
4676  return false;
4677 }
4678 
4679 /* inherits documentation from base class */
4680 QList<QCPLayoutElement*> QCPLayoutGrid::elements(bool recursive) const
4681 {
4682  QList<QCPLayoutElement*> result;
4683  const int elCount = elementCount();
4684 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
4685  result.reserve(elCount);
4686 #endif
4687  for (int i=0; i<elCount; ++i)
4688  result.append(elementAt(i));
4689  if (recursive)
4690  {
4691  for (int i=0; i<elCount; ++i)
4692  {
4693  if (result.at(i))
4694  result << result.at(i)->elements(recursive);
4695  }
4696  }
4697  return result;
4698 }
4699 
4704 {
4705  // remove rows with only empty cells:
4706  for (int row=rowCount()-1; row>=0; --row)
4707  {
4708  bool hasElements = false;
4709  for (int col=0; col<columnCount(); ++col)
4710  {
4711  if (mElements.at(row).at(col))
4712  {
4713  hasElements = true;
4714  break;
4715  }
4716  }
4717  if (!hasElements)
4718  {
4719  mRowStretchFactors.removeAt(row);
4720  mElements.removeAt(row);
4721  if (mElements.isEmpty()) // removed last element, also remove stretch factor (wouldn't happen below because also columnCount changed to 0 now)
4722  mColumnStretchFactors.clear();
4723  }
4724  }
4725 
4726  // remove columns with only empty cells:
4727  for (int col=columnCount()-1; col>=0; --col)
4728  {
4729  bool hasElements = false;
4730  for (int row=0; row<rowCount(); ++row)
4731  {
4732  if (mElements.at(row).at(col))
4733  {
4734  hasElements = true;
4735  break;
4736  }
4737  }
4738  if (!hasElements)
4739  {
4740  mColumnStretchFactors.removeAt(col);
4741  for (int row=0; row<rowCount(); ++row)
4742  mElements[row].removeAt(col);
4743  }
4744  }
4745 }
4746 
4747 /* inherits documentation from base class */
4749 {
4750  QVector<int> minColWidths, minRowHeights;
4751  getMinimumRowColSizes(&minColWidths, &minRowHeights);
4752  QSize result(0, 0);
4753  foreach (int w, minColWidths)
4754  result.rwidth() += w;
4755  foreach (int h, minRowHeights)
4756  result.rheight() += h;
4757  result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing;
4758  result.rheight() += qMax(0, rowCount()-1) * mRowSpacing;
4759  result.rwidth() += mMargins.left()+mMargins.right();
4760  result.rheight() += mMargins.top()+mMargins.bottom();
4761  return result;
4762 }
4763 
4764 /* inherits documentation from base class */
4766 {
4767  QVector<int> maxColWidths, maxRowHeights;
4768  getMaximumRowColSizes(&maxColWidths, &maxRowHeights);
4769 
4770  QSize result(0, 0);
4771  foreach (int w, maxColWidths)
4772  result.setWidth(qMin(result.width()+w, QWIDGETSIZE_MAX));
4773  foreach (int h, maxRowHeights)
4774  result.setHeight(qMin(result.height()+h, QWIDGETSIZE_MAX));
4775  result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing;
4776  result.rheight() += qMax(0, rowCount()-1) * mRowSpacing;
4777  result.rwidth() += mMargins.left()+mMargins.right();
4778  result.rheight() += mMargins.top()+mMargins.bottom();
4779  if (result.height() > QWIDGETSIZE_MAX)
4780  result.setHeight(QWIDGETSIZE_MAX);
4781  if (result.width() > QWIDGETSIZE_MAX)
4782  result.setWidth(QWIDGETSIZE_MAX);
4783  return result;
4784 }
4785 
4799 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, QVector<int> *minRowHeights) const
4800 {
4801  *minColWidths = QVector<int>(columnCount(), 0);
4802  *minRowHeights = QVector<int>(rowCount(), 0);
4803  for (int row=0; row<rowCount(); ++row)
4804  {
4805  for (int col=0; col<columnCount(); ++col)
4806  {
4807  if (QCPLayoutElement *el = mElements.at(row).at(col))
4808  {
4809  QSize minSize = getFinalMinimumOuterSize(el);
4810  if (minColWidths->at(col) < minSize.width())
4811  (*minColWidths)[col] = minSize.width();
4812  if (minRowHeights->at(row) < minSize.height())
4813  (*minRowHeights)[row] = minSize.height();
4814  }
4815  }
4816  }
4817 }
4818 
4832 void QCPLayoutGrid::getMaximumRowColSizes(QVector<int> *maxColWidths, QVector<int> *maxRowHeights) const
4833 {
4834  *maxColWidths = QVector<int>(columnCount(), QWIDGETSIZE_MAX);
4835  *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX);
4836  for (int row=0; row<rowCount(); ++row)
4837  {
4838  for (int col=0; col<columnCount(); ++col)
4839  {
4840  if (QCPLayoutElement *el = mElements.at(row).at(col))
4841  {
4842  QSize maxSize = getFinalMaximumOuterSize(el);
4843  if (maxColWidths->at(col) > maxSize.width())
4844  (*maxColWidths)[col] = maxSize.width();
4845  if (maxRowHeights->at(row) > maxSize.height())
4846  (*maxRowHeights)[row] = maxSize.height();
4847  }
4848  }
4849  }
4850 }
4851 
4852 
4856 
4874 /* start documentation of inline functions */
4875 
4882 /* end documentation of inline functions */
4883 
4888 {
4889 }
4890 
4892 {
4893  // clear all child layout elements. This is important because only the specific layouts know how
4894  // to handle removing elements (clear calls virtual removeAt method to do that).
4895  clear();
4896 }
4897 
4902 {
4903  if (elementAt(index))
4904  return mInsetPlacement.at(index);
4905  else
4906  {
4907  qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
4908  return ipFree;
4909  }
4910 }
4911 
4916 Qt::Alignment QCPLayoutInset::insetAlignment(int index) const
4917 {
4918  if (elementAt(index))
4919  return mInsetAlignment.at(index);
4920  else
4921  {
4922  qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
4923 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
4924  return nullptr;
4925 #else
4926  return {};
4927 #endif
4928  }
4929 }
4930 
4935 QRectF QCPLayoutInset::insetRect(int index) const
4936 {
4937  if (elementAt(index))
4938  return mInsetRect.at(index);
4939  else
4940  {
4941  qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
4942  return {};
4943  }
4944 }
4945 
4952 {
4953  if (elementAt(index))
4954  mInsetPlacement[index] = placement;
4955  else
4956  qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
4957 }
4958 
4967 void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment)
4968 {
4969  if (elementAt(index))
4970  mInsetAlignment[index] = alignment;
4971  else
4972  qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
4973 }
4974 
4986 void QCPLayoutInset::setInsetRect(int index, const QRectF &rect)
4987 {
4988  if (elementAt(index))
4989  mInsetRect[index] = rect;
4990  else
4991  qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
4992 }
4993 
4994 /* inherits documentation from base class */
4996 {
4997  for (int i=0; i<mElements.size(); ++i)
4998  {
4999  QCPLayoutElement *el = mElements.at(i);
5000  QRect insetRect;
5001  QSize finalMinSize = getFinalMinimumOuterSize(el);
5002  QSize finalMaxSize = getFinalMaximumOuterSize(el);
5003  if (mInsetPlacement.at(i) == ipFree)
5004  {
5005  insetRect = QRect(int( rect().x()+rect().width()*mInsetRect.at(i).x() ),
5006  int( rect().y()+rect().height()*mInsetRect.at(i).y() ),
5007  int( rect().width()*mInsetRect.at(i).width() ),
5008  int( rect().height()*mInsetRect.at(i).height() ));
5009  if (insetRect.size().width() < finalMinSize.width())
5010  insetRect.setWidth(finalMinSize.width());
5011  if (insetRect.size().height() < finalMinSize.height())
5012  insetRect.setHeight(finalMinSize.height());
5013  if (insetRect.size().width() > finalMaxSize.width())
5014  insetRect.setWidth(finalMaxSize.width());
5015  if (insetRect.size().height() > finalMaxSize.height())
5016  insetRect.setHeight(finalMaxSize.height());
5017  } else if (mInsetPlacement.at(i) == ipBorderAligned)
5018  {
5019  insetRect.setSize(finalMinSize);
5020  Qt::Alignment al = mInsetAlignment.at(i);
5021  if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x());
5022  else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width());
5023  else insetRect.moveLeft(int( rect().x()+rect().width()*0.5-finalMinSize.width()*0.5 )); // default to Qt::AlignHCenter
5024  if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y());
5025  else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height());
5026  else insetRect.moveTop(int( rect().y()+rect().height()*0.5-finalMinSize.height()*0.5 )); // default to Qt::AlignVCenter
5027  }
5028  mElements.at(i)->setOuterRect(insetRect);
5029  }
5030 }
5031 
5032 /* inherits documentation from base class */
5034 {
5035  return mElements.size();
5036 }
5037 
5038 /* inherits documentation from base class */
5040 {
5041  if (index >= 0 && index < mElements.size())
5042  return mElements.at(index);
5043  else
5044  return nullptr;
5045 }
5046 
5047 /* inherits documentation from base class */
5049 {
5050  if (QCPLayoutElement *el = elementAt(index))
5051  {
5052  releaseElement(el);
5053  mElements.removeAt(index);
5054  mInsetPlacement.removeAt(index);
5055  mInsetAlignment.removeAt(index);
5056  mInsetRect.removeAt(index);
5057  return el;
5058  } else
5059  {
5060  qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index;
5061  return nullptr;
5062  }
5063 }
5064 
5065 /* inherits documentation from base class */
5067 {
5068  if (element)
5069  {
5070  for (int i=0; i<elementCount(); ++i)
5071  {
5072  if (elementAt(i) == element)
5073  {
5074  takeAt(i);
5075  return true;
5076  }
5077  }
5078  qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take";
5079  } else
5080  qDebug() << Q_FUNC_INFO << "Can't take nullptr element";
5081  return false;
5082 }
5083 
5093 double QCPLayoutInset::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
5094 {
5095  Q_UNUSED(details)
5096  if (onlySelectable)
5097  return -1;
5098 
5099  foreach (QCPLayoutElement *el, mElements)
5100  {
5101  // inset layout shall only return positive selectTest, if actually an inset object is at pos
5102  // else it would block the entire underlying QCPAxisRect with its surface.
5103  if (el->realVisibility() && el->selectTest(pos, onlySelectable) >= 0)
5104  return mParentPlot->selectionTolerance()*0.99;
5105  }
5106  return -1;
5107 }
5108 
5120 void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment)
5121 {
5122  if (element)
5123  {
5124  if (element->layout()) // remove from old layout first
5125  element->layout()->take(element);
5126  mElements.append(element);
5128  mInsetAlignment.append(alignment);
5129  mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4));
5130  adoptElement(element);
5131  } else
5132  qDebug() << Q_FUNC_INFO << "Can't add nullptr element";
5133 }
5134 
5146 void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect)
5147 {
5148  if (element)
5149  {
5150  if (element->layout()) // remove from old layout first
5151  element->layout()->take(element);
5152  mElements.append(element);
5153  mInsetPlacement.append(ipFree);
5154  mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop);
5155  mInsetRect.append(rect);
5156  adoptElement(element);
5157  } else
5158  qDebug() << Q_FUNC_INFO << "Can't add nullptr element";
5159 }
5160 /* end of 'src/layout.cpp' */
5161 
5162 
5163 /* including file 'src/lineending.cpp' */
5164 /* modified 2021-03-29T02:30:44, size 11189 */
5165 
5169 
5194  mStyle(esNone),
5195  mWidth(8),
5196  mLength(10),
5197  mInverted(false)
5198 {
5199 }
5200 
5204 QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) :
5205  mStyle(style),
5206  mWidth(width),
5207  mLength(length),
5208  mInverted(inverted)
5209 {
5210 }
5211 
5216 {
5217  mStyle = style;
5218 }
5219 
5226 void QCPLineEnding::setWidth(double width)
5227 {
5228  mWidth = width;
5229 }
5230 
5237 void QCPLineEnding::setLength(double length)
5238 {
5239  mLength = length;
5240 }
5241 
5250 void QCPLineEnding::setInverted(bool inverted)
5251 {
5252  mInverted = inverted;
5253 }
5254 
5265 {
5266  switch (mStyle)
5267  {
5268  case esNone:
5269  return 0;
5270 
5271  case esFlatArrow:
5272  case esSpikeArrow:
5273  case esLineArrow:
5274  case esSkewedBar:
5275  return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length
5276 
5277  case esDisc:
5278  case esSquare:
5279  case esDiamond:
5280  case esBar:
5281  case esHalfBar:
5282  return mWidth*1.42; // items that only have a width -> width*sqrt(2)
5283 
5284  }
5285  return 0;
5286 }
5287 
5300 {
5301  switch (mStyle)
5302  {
5303  case esNone:
5304  case esLineArrow:
5305  case esSkewedBar:
5306  case esBar:
5307  case esHalfBar:
5308  return 0;
5309 
5310  case esFlatArrow:
5311  return mLength;
5312 
5313  case esDisc:
5314  case esSquare:
5315  case esDiamond:
5316  return mWidth*0.5;
5317 
5318  case esSpikeArrow:
5319  return mLength*0.8;
5320  }
5321  return 0;
5322 }
5323 
5329 void QCPLineEnding::draw(QCPPainter *painter, const QCPVector2D &pos, const QCPVector2D &dir) const
5330 {
5331  if (mStyle == esNone)
5332  return;
5333 
5334  QCPVector2D lengthVec = dir.normalized() * mLength*(mInverted ? -1 : 1);
5335  if (lengthVec.isNull())
5336  lengthVec = QCPVector2D(1, 0);
5337  QCPVector2D widthVec = dir.normalized().perpendicular() * mWidth*0.5*(mInverted ? -1 : 1);
5338 
5339  QPen penBackup = painter->pen();
5340  QBrush brushBackup = painter->brush();
5341  QPen miterPen = penBackup;
5342  miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey
5343  QBrush brush(painter->pen().color(), Qt::SolidPattern);
5344  switch (mStyle)
5345  {
5346  case esNone: break;
5347  case esFlatArrow:
5348  {
5349  QPointF points[3] = {pos.toPointF(),
5350  (pos-lengthVec+widthVec).toPointF(),
5351  (pos-lengthVec-widthVec).toPointF()
5352  };
5353  painter->setPen(miterPen);
5354  painter->setBrush(brush);
5355  painter->drawConvexPolygon(points, 3);
5356  painter->setBrush(brushBackup);
5357  painter->setPen(penBackup);
5358  break;
5359  }
5360  case esSpikeArrow:
5361  {
5362  QPointF points[4] = {pos.toPointF(),
5363  (pos-lengthVec+widthVec).toPointF(),
5364  (pos-lengthVec*0.8).toPointF(),
5365  (pos-lengthVec-widthVec).toPointF()
5366  };
5367  painter->setPen(miterPen);
5368  painter->setBrush(brush);
5369  painter->drawConvexPolygon(points, 4);
5370  painter->setBrush(brushBackup);
5371  painter->setPen(penBackup);
5372  break;
5373  }
5374  case esLineArrow:
5375  {
5376  QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(),
5377  pos.toPointF(),
5378  (pos-lengthVec-widthVec).toPointF()
5379  };
5380  painter->setPen(miterPen);
5381  painter->drawPolyline(points, 3);
5382  painter->setPen(penBackup);
5383  break;
5384  }
5385  case esDisc:
5386  {
5387  painter->setBrush(brush);
5388  painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5);
5389  painter->setBrush(brushBackup);
5390  break;
5391  }
5392  case esSquare:
5393  {
5394  QCPVector2D widthVecPerp = widthVec.perpendicular();
5395  QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(),
5396  (pos-widthVecPerp-widthVec).toPointF(),
5397  (pos+widthVecPerp-widthVec).toPointF(),
5398  (pos+widthVecPerp+widthVec).toPointF()
5399  };
5400  painter->setPen(miterPen);
5401  painter->setBrush(brush);
5402  painter->drawConvexPolygon(points, 4);
5403  painter->setBrush(brushBackup);
5404  painter->setPen(penBackup);
5405  break;
5406  }
5407  case esDiamond:
5408  {
5409  QCPVector2D widthVecPerp = widthVec.perpendicular();
5410  QPointF points[4] = {(pos-widthVecPerp).toPointF(),
5411  (pos-widthVec).toPointF(),
5412  (pos+widthVecPerp).toPointF(),
5413  (pos+widthVec).toPointF()
5414  };
5415  painter->setPen(miterPen);
5416  painter->setBrush(brush);
5417  painter->drawConvexPolygon(points, 4);
5418  painter->setBrush(brushBackup);
5419  painter->setPen(penBackup);
5420  break;
5421  }
5422  case esBar:
5423  {
5424  painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF());
5425  break;
5426  }
5427  case esHalfBar:
5428  {
5429  painter->drawLine((pos+widthVec).toPointF(), pos.toPointF());
5430  break;
5431  }
5432  case esSkewedBar:
5433  {
5434  QCPVector2D shift;
5435  if (!qFuzzyIsNull(painter->pen().widthF()) || painter->modes().testFlag(QCPPainter::pmNonCosmetic))
5436  shift = dir.normalized()*qMax(qreal(1.0), painter->pen().widthF())*qreal(0.5);
5437  // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly
5438  painter->drawLine((pos+widthVec+lengthVec*0.2*(mInverted?-1:1)+shift).toPointF(),
5439  (pos-widthVec-lengthVec*0.2*(mInverted?-1:1)+shift).toPointF());
5440  break;
5441  }
5442  }
5443 }
5444 
5450 void QCPLineEnding::draw(QCPPainter *painter, const QCPVector2D &pos, double angle) const
5451 {
5452  draw(painter, pos, QCPVector2D(qCos(angle), qSin(angle)));
5453 }
5454 /* end of 'src/lineending.cpp' */
5455 
5456 
5457 /* including file 'src/axis/labelpainter.cpp' */
5458 /* modified 2021-03-29T02:30:44, size 27296 */
5459 
5460 
5464 
5474 const QChar QCPLabelPainterPrivate::SymbolDot(183);
5475 const QChar QCPLabelPainterPrivate::SymbolCross(215);
5476 
5485  mAnchorMode(amRectangular),
5486  mAnchorSide(asLeft),
5487  mAnchorReferenceType(artNormal),
5488  mColor(Qt::black),
5489  mPadding(0),
5490  mRotation(0),
5491  mSubstituteExponent(true),
5492  mMultiplicationSymbol(QChar(215)),
5493  mAbbreviateDecimalPowers(false),
5494  mParentPlot(parentPlot),
5495  mLabelCache(16)
5496 {
5498 }
5499 
5501 {
5502 }
5503 
5505 {
5506  mAnchorSide = side;
5507 }
5508 
5510 {
5511  mAnchorMode = mode;
5512 }
5513 
5514 void QCPLabelPainterPrivate::setAnchorReference(const QPointF &pixelPoint)
5515 {
5516  mAnchorReference = pixelPoint;
5517 }
5518 
5520 {
5521  mAnchorReferenceType = type;
5522 }
5523 
5524 void QCPLabelPainterPrivate::setFont(const QFont &font)
5525 {
5526  if (mFont != font)
5527  {
5528  mFont = font;
5530  }
5531 }
5532 
5534 {
5535  mColor = color;
5536 }
5537 
5539 {
5540  mPadding = padding;
5541 }
5542 
5544 {
5545  mRotation = qBound(-90.0, rotation, 90.0);
5546 }
5547 
5549 {
5550  mSubstituteExponent = enabled;
5551 }
5552 
5554 {
5555  mMultiplicationSymbol = symbol;
5556 }
5557 
5559 {
5560  mAbbreviateDecimalPowers = enabled;
5561 }
5562 
5564 {
5565  mLabelCache.setMaxCost(labelCount);
5566 }
5567 
5569 {
5570  return mLabelCache.maxCost();
5571 }
5572 
5573 void QCPLabelPainterPrivate::drawTickLabel(QCPPainter *painter, const QPointF &tickPos, const QString &text)
5574 {
5575  double realRotation = mRotation;
5576 
5577  AnchorSide realSide = mAnchorSide;
5578  // for circular axes, the anchor side is determined depending on the quadrant of tickPos with respect to mCircularReference
5580  {
5581  realSide = skewedAnchorSide(tickPos, 0.2, 0.3);
5582  } else if (mAnchorMode == amSkewedRotated) // in this mode every label is individually rotated to match circle tangent
5583  {
5584  realSide = skewedAnchorSide(tickPos, 0, 0);
5585  realRotation += QCPVector2D(tickPos-mAnchorReference).angle()/M_PI*180.0;
5586  if (realRotation > 90) realRotation -= 180;
5587  else if (realRotation < -90) realRotation += 180;
5588  }
5589 
5590  realSide = rotationCorrectedSide(realSide, realRotation); // rotation angles may change the true anchor side of the label
5591  drawLabelMaybeCached(painter, mFont, mColor, getAnchorPos(tickPos), realSide, realRotation, text);
5592 }
5593 
5599 /* TODO: needed?
5600 int QCPLabelPainterPrivate::size() const
5601 {
5602  int result = 0;
5603  // get length of tick marks pointing outwards:
5604  if (!tickPositions.isEmpty())
5605  result += qMax(0, qMax(tickLengthOut, subTickLengthOut));
5606 
5607  // calculate size of tick labels:
5608  if (tickLabelSide == QCPAxis::lsOutside)
5609  {
5610  QSize tickLabelsSize(0, 0);
5611  if (!tickLabels.isEmpty())
5612  {
5613  for (int i=0; i<tickLabels.size(); ++i)
5614  getMaxTickLabelSize(tickLabelFont, tickLabels.at(i), &tickLabelsSize);
5615  result += QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width();
5616  result += tickLabelPadding;
5617  }
5618  }
5619 
5620  // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees):
5621  if (!label.isEmpty())
5622  {
5623  QFontMetrics fontMetrics(labelFont);
5624  QRect bounds;
5625  bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label);
5626  result += bounds.height() + labelPadding;
5627  }
5628 
5629  return result;
5630 }
5631 */
5632 
5640 {
5641  mLabelCache.clear();
5642 }
5643 
5652 {
5653  QByteArray result;
5654  result.append(QByteArray::number(mParentPlot->bufferDevicePixelRatio()));
5655  result.append(QByteArray::number(mRotation));
5656  //result.append(QByteArray::number((int)tickLabelSide)); TODO: check whether this is really a cache-invalidating property
5657  result.append(QByteArray::number((int)mSubstituteExponent));
5658  result.append(QString(mMultiplicationSymbol).toUtf8());
5659  result.append(mColor.name().toLatin1()+QByteArray::number(mColor.alpha(), 16));
5660  result.append(mFont.toString().toLatin1());
5661  return result;
5662 }
5663 
5683 void QCPLabelPainterPrivate::drawLabelMaybeCached(QCPPainter *painter, const QFont &font, const QColor &color, const QPointF &pos, AnchorSide side, double rotation, const QString &text)
5684 {
5685  // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly!
5686  if (text.isEmpty()) return;
5687  QSize finalSize;
5688 
5689  if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled
5690  {
5691  QByteArray key = cacheKey(text, color, rotation, side);
5692  CachedLabel *cachedLabel = mLabelCache.take(QString::fromUtf8(key)); // attempt to take label from cache (don't use object() because we want ownership/prevent deletion during our operations, we re-insert it afterwards)
5693  if (!cachedLabel) // no cached label existed, create it
5694  {
5695  LabelData labelData = getTickLabelData(font, color, rotation, side, text);
5696  cachedLabel = createCachedLabel(labelData);
5697  }
5698  // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
5699  bool labelClippedByBorder = false;
5700  /*
5701  if (tickLabelSide == QCPAxis::lsOutside)
5702  {
5703  if (QCPAxis::orientation(type) == Qt::Horizontal)
5704  labelClippedByBorder = labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width()/mParentPlot->bufferDevicePixelRatio() > viewportRect.right() || labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left();
5705  else
5706  labelClippedByBorder = labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height()/mParentPlot->bufferDevicePixelRatio() > viewportRect.bottom() || labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top();
5707  }
5708  */
5709  if (!labelClippedByBorder)
5710  {
5711  painter->drawPixmap(pos+cachedLabel->offset, cachedLabel->pixmap);
5712  finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio(); // TODO: collect this in a member rect list?
5713  }
5714  mLabelCache.insert(QString::fromUtf8(key), cachedLabel);
5715  } else // label caching disabled, draw text directly on surface:
5716  {
5717  LabelData labelData = getTickLabelData(font, color, rotation, side, text);
5718  // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
5719  bool labelClippedByBorder = false;
5720  /*
5721  if (tickLabelSide == QCPAxis::lsOutside)
5722  {
5723  if (QCPAxis::orientation(type) == Qt::Horizontal)
5724  labelClippedByBorder = finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left();
5725  else
5726  labelClippedByBorder = finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top();
5727  }
5728  */
5729  if (!labelClippedByBorder)
5730  {
5731  drawText(painter, pos, labelData);
5732  finalSize = labelData.rotatedTotalBounds.size();
5733  }
5734  }
5735  /*
5736  // expand passed tickLabelsSize if current tick label is larger:
5737  if (finalSize.width() > tickLabelsSize->width())
5738  tickLabelsSize->setWidth(finalSize.width());
5739  if (finalSize.height() > tickLabelsSize->height())
5740  tickLabelsSize->setHeight(finalSize.height());
5741  */
5742 }
5743 
5744 QPointF QCPLabelPainterPrivate::getAnchorPos(const QPointF &tickPos)
5745 {
5746  switch (mAnchorMode)
5747  {
5748  case amRectangular:
5749  {
5750  switch (mAnchorSide)
5751  {
5752  case asLeft: return tickPos+QPointF(mPadding, 0);
5753  case asRight: return tickPos+QPointF(-mPadding, 0);
5754  case asTop: return tickPos+QPointF(0, mPadding);
5755  case asBottom: return tickPos+QPointF(0, -mPadding);
5756  case asTopLeft: return tickPos+QPointF(mPadding*M_SQRT1_2, mPadding*M_SQRT1_2);
5757  case asTopRight: return tickPos+QPointF(-mPadding*M_SQRT1_2, mPadding*M_SQRT1_2);
5758  case asBottomRight: return tickPos+QPointF(-mPadding*M_SQRT1_2, -mPadding*M_SQRT1_2);
5759  case asBottomLeft: return tickPos+QPointF(mPadding*M_SQRT1_2, -mPadding*M_SQRT1_2);
5760  }
5761  }
5762  case amSkewedUpright:
5763  case amSkewedRotated:
5764  {
5765  QCPVector2D anchorNormal(tickPos-mAnchorReference);
5767  anchorNormal = anchorNormal.perpendicular();
5768  anchorNormal.normalize();
5769  return tickPos+(anchorNormal*mPadding).toPointF();
5770  }
5771  }
5772  return tickPos;
5773 }
5774 
5784 void QCPLabelPainterPrivate::drawText(QCPPainter *painter, const QPointF &pos, const LabelData &labelData) const
5785 {
5786  // backup painter settings that we're about to change:
5787  QTransform oldTransform = painter->transform();
5788  QFont oldFont = painter->font();
5789  QPen oldPen = painter->pen();
5790 
5791  // transform painter to position/rotation:
5792  painter->translate(pos);
5793  painter->setTransform(labelData.transform, true);
5794 
5795  // draw text:
5796  painter->setFont(labelData.baseFont);
5797  painter->setPen(QPen(labelData.color));
5798  if (!labelData.expPart.isEmpty()) // use superscripted exponent typesetting
5799  {
5800  painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart);
5801  if (!labelData.suffixPart.isEmpty())
5802  painter->drawText(labelData.baseBounds.width()+1+labelData.expBounds.width(), 0, 0, 0, Qt::TextDontClip, labelData.suffixPart);
5803  painter->setFont(labelData.expFont);
5804  painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart);
5805  } else
5806  {
5807  painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart);
5808  }
5809 
5810  /* Debug code to draw label bounding boxes, baseline, and capheight
5811  painter->save();
5812  painter->setPen(QPen(QColor(0, 0, 0, 150)));
5813  painter->drawRect(labelData.totalBounds);
5814  const int baseline = labelData.totalBounds.height()-mLetterDescent;
5815  painter->setPen(QPen(QColor(255, 0, 0, 150)));
5816  painter->drawLine(QLineF(0, baseline, labelData.totalBounds.width(), baseline));
5817  painter->setPen(QPen(QColor(0, 0, 255, 150)));
5818  painter->drawLine(QLineF(0, baseline-mLetterCapHeight, labelData.totalBounds.width(), baseline-mLetterCapHeight));
5819  painter->restore();
5820  */
5821 
5822  // reset painter settings to what it was before:
5823  painter->setTransform(oldTransform);
5824  painter->setFont(oldFont);
5825  painter->setPen(oldPen);
5826 }
5827 
5836 QCPLabelPainterPrivate::LabelData QCPLabelPainterPrivate::getTickLabelData(const QFont &font, const QColor &color, double rotation, AnchorSide side, const QString &text) const
5837 {
5838  LabelData result;
5839  result.rotation = rotation;
5840  result.side = side;
5841  result.color = color;
5842 
5843  // determine whether beautiful decimal powers should be used
5844  bool useBeautifulPowers = false;
5845  int ePos = -1; // first index of exponent part, text before that will be basePart, text until eLast will be expPart
5846  int eLast = -1; // last index of exponent part, rest of text after this will be suffixPart
5847  if (mSubstituteExponent)
5848  {
5849  ePos = text.indexOf(QLatin1Char('e'));
5850  if (ePos > 0 && text.at(ePos-1).isDigit())
5851  {
5852  eLast = ePos;
5853  while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char('+') || text.at(eLast+1) == QLatin1Char('-') || text.at(eLast+1).isDigit()))
5854  ++eLast;
5855  if (eLast > ePos) // only if also to right of 'e' is a digit/+/- interpret it as beautifiable power
5856  useBeautifulPowers = true;
5857  }
5858  }
5859 
5860  // calculate text bounding rects and do string preparation for beautiful decimal powers:
5861  result.baseFont = font;
5862  if (result.baseFont.pointSizeF() > 0) // might return -1 if specified with setPixelSize, in that case we can't do correction in next line
5863  result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding
5864 
5865  QFontMetrics baseFontMetrics(result.baseFont);
5866  if (useBeautifulPowers)
5867  {
5868  // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent:
5869  result.basePart = text.left(ePos);
5870  result.suffixPart = text.mid(eLast+1); // also drawn normally but after exponent
5871  // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base:
5872  if (mAbbreviateDecimalPowers && result.basePart == QLatin1String("1"))
5873  result.basePart = QLatin1String("10");
5874  else
5875  result.basePart += QString(mMultiplicationSymbol) + QLatin1String("10");
5876  result.expPart = text.mid(ePos+1, eLast-ePos);
5877  // clip "+" and leading zeros off expPart:
5878  while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e'
5879  result.expPart.remove(1, 1);
5880  if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+'))
5881  result.expPart.remove(0, 1);
5882  // prepare smaller font for exponent:
5883  result.expFont = font;
5884  if (result.expFont.pointSize() > 0)
5885  result.expFont.setPointSize(result.expFont.pointSize()*0.75);
5886  else
5887  result.expFont.setPixelSize(result.expFont.pixelSize()*0.75);
5888  // calculate bounding rects of base part(s), exponent part and total one:
5889  result.baseBounds = baseFontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart);
5890  result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart);
5891  if (!result.suffixPart.isEmpty())
5892  result.suffixBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.suffixPart);
5893  result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+result.suffixBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA
5894  } else // useBeautifulPowers == false
5895  {
5896  result.basePart = text;
5897  result.totalBounds = baseFontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart);
5898  }
5899  result.totalBounds.moveTopLeft(QPoint(0, 0));
5900  applyAnchorTransform(result);
5901  result.rotatedTotalBounds = result.transform.mapRect(result.totalBounds);
5902 
5903  return result;
5904 }
5905 
5907 {
5908  if (!qFuzzyIsNull(labelData.rotation))
5909  labelData.transform.rotate(labelData.rotation); // rotates effectively clockwise (due to flipped y axis of painter vs widget coordinate system)
5910 
5911  // from now on we translate in rotated label-local coordinate system.
5912  // shift origin of coordinate system to appropriate point on label:
5913  labelData.transform.translate(0, -labelData.totalBounds.height()+mLetterDescent+mLetterCapHeight); // shifts origin to true top of capital (or number) characters
5914 
5915  if (labelData.side == asLeft || labelData.side == asRight) // anchor is centered vertically
5916  labelData.transform.translate(0, -mLetterCapHeight/2.0);
5917  else if (labelData.side == asTop || labelData.side == asBottom) // anchor is centered horizontally
5918  labelData.transform.translate(-labelData.totalBounds.width()/2.0, 0);
5919 
5920  if (labelData.side == asTopRight || labelData.side == asRight || labelData.side == asBottomRight) // anchor is at right
5921  labelData.transform.translate(-labelData.totalBounds.width(), 0);
5922  if (labelData.side == asBottomLeft || labelData.side == asBottom || labelData.side == asBottomRight) // anchor is at bottom (no elseif!)
5923  labelData.transform.translate(0, -mLetterCapHeight);
5924 }
5925 
5933 /*
5934 void QCPLabelPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const
5935 {
5936  // note: this function must return the same tick label sizes as the placeTickLabel function.
5937  QSize finalSize;
5938  if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label
5939  {
5940  const CachedLabel *cachedLabel = mLabelCache.object(text);
5941  finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio();
5942  } else // label caching disabled or no label with this text cached:
5943  {
5944  // TODO: LabelData labelData = getTickLabelData(font, text);
5945  // TODO: finalSize = labelData.rotatedTotalBounds.size();
5946  }
5947 
5948  // expand passed tickLabelsSize if current tick label is larger:
5949  if (finalSize.width() > tickLabelsSize->width())
5950  tickLabelsSize->setWidth(finalSize.width());
5951  if (finalSize.height() > tickLabelsSize->height())
5952  tickLabelsSize->setHeight(finalSize.height());
5953 }
5954 */
5955 
5957 {
5958  CachedLabel *result = new CachedLabel;
5959 
5960  // allocate pixmap with the correct size and pixel ratio:
5961  if (!qFuzzyCompare(1.0, mParentPlot->bufferDevicePixelRatio()))
5962  {
5963  result->pixmap = QPixmap(labelData.rotatedTotalBounds.size()*mParentPlot->bufferDevicePixelRatio());
5964 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
5965 # ifdef QCP_DEVICEPIXELRATIO_FLOAT
5966  result->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatioF());
5967 # else
5968  result->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio());
5969 # endif
5970 #endif
5971  } else
5972  result->pixmap = QPixmap(labelData.rotatedTotalBounds.size());
5973  result->pixmap.fill(Qt::transparent);
5974 
5975  // draw the label into the pixmap
5976  // offset is between label anchor and topleft of cache pixmap, so pixmap can be drawn at pos+offset to make the label anchor appear at pos.
5977  // We use rotatedTotalBounds.topLeft() because rotatedTotalBounds is in a coordinate system where the label anchor is at (0, 0)
5978  result->offset = labelData.rotatedTotalBounds.topLeft();
5979  QCPPainter cachePainter(&result->pixmap);
5980  drawText(&cachePainter, -result->offset, labelData);
5981  return result;
5982 }
5983 
5984 QByteArray QCPLabelPainterPrivate::cacheKey(const QString &text, const QColor &color, double rotation, AnchorSide side) const
5985 {
5986  return text.toUtf8()+
5987  QByteArray::number(color.red()+256*color.green()+65536*color.blue(), 36)+
5988  QByteArray::number(color.alpha()+256*(int)side, 36)+
5989  QByteArray::number((int)(rotation*100)%36000, 36);
5990 }
5991 
5992 QCPLabelPainterPrivate::AnchorSide QCPLabelPainterPrivate::skewedAnchorSide(const QPointF &tickPos, double sideExpandHorz, double sideExpandVert) const
5993 {
5994  QCPVector2D anchorNormal = QCPVector2D(tickPos-mAnchorReference);
5996  anchorNormal = anchorNormal.perpendicular();
5997  const double radius = anchorNormal.length();
5998  const double sideHorz = sideExpandHorz*radius;
5999  const double sideVert = sideExpandVert*radius;
6000  if (anchorNormal.x() > sideHorz)
6001  {
6002  if (anchorNormal.y() > sideVert) return asTopLeft;
6003  else if (anchorNormal.y() < -sideVert) return asBottomLeft;
6004  else return asLeft;
6005  } else if (anchorNormal.x() < -sideHorz)
6006  {
6007  if (anchorNormal.y() > sideVert) return asTopRight;
6008  else if (anchorNormal.y() < -sideVert) return asBottomRight;
6009  else return asRight;
6010  } else
6011  {
6012  if (anchorNormal.y() > 0) return asTop;
6013  else return asBottom;
6014  }
6015  return asBottom; // should never be reached
6016 }
6017 
6019 {
6020  AnchorSide result = side;
6021  const bool rotateClockwise = rotation > 0;
6022  if (!qFuzzyIsNull(rotation))
6023  {
6024  if (!qFuzzyCompare(qAbs(rotation), 90)) // avoid graphical collision with anchor tangent (e.g. axis line) when rotating, so change anchor side appropriately:
6025  {
6026  if (side == asTop) result = rotateClockwise ? asLeft : asRight;
6027  else if (side == asBottom) result = rotateClockwise ? asRight : asLeft;
6028  else if (side == asTopLeft) result = rotateClockwise ? asLeft : asTop;
6029  else if (side == asTopRight) result = rotateClockwise ? asTop : asRight;
6030  else if (side == asBottomLeft) result = rotateClockwise ? asBottom : asLeft;
6031  else if (side == asBottomRight) result = rotateClockwise ? asRight : asBottom;
6032  } else // for full rotation by +/-90 degrees, other sides are more appropriate for centering on anchor:
6033  {
6034  if (side == asLeft) result = rotateClockwise ? asBottom : asTop;
6035  else if (side == asRight) result = rotateClockwise ? asTop : asBottom;
6036  else if (side == asTop) result = rotateClockwise ? asLeft : asRight;
6037  else if (side == asBottom) result = rotateClockwise ? asRight : asLeft;
6038  else if (side == asTopLeft) result = rotateClockwise ? asBottomLeft : asTopRight;
6039  else if (side == asTopRight) result = rotateClockwise ? asTopLeft : asBottomRight;
6040  else if (side == asBottomLeft) result = rotateClockwise ? asBottomRight : asTopLeft;
6041  else if (side == asBottomRight) result = rotateClockwise ? asTopRight : asBottomLeft;
6042  }
6043  }
6044  return result;
6045 }
6046 
6048 {
6049  const QFontMetrics fm(mFont);
6050  mLetterCapHeight = fm.tightBoundingRect(QLatin1String("8")).height(); // this method is slow, that's why we query it only upon font change
6051  mLetterDescent = fm.descent();
6052 }
6053 /* end of 'src/axis/labelpainter.cpp' */
6054 
6055 
6056 /* including file 'src/axis/axisticker.cpp' */
6057 /* modified 2021-03-29T02:30:44, size 18688 */
6058 
6062 
6120  mTickStepStrategy(tssReadability),
6121  mTickCount(5),
6122  mTickOrigin(0)
6123 {
6124 }
6125 
6127 {
6128 
6129 }
6130 
6136 {
6137  mTickStepStrategy = strategy;
6138 }
6139 
6149 {
6150  if (count > 0)
6151  mTickCount = count;
6152  else
6153  qDebug() << Q_FUNC_INFO << "tick count must be greater than zero:" << count;
6154 }
6155 
6164 void QCPAxisTicker::setTickOrigin(double origin)
6165 {
6166  mTickOrigin = origin;
6167 }
6168 
6182 void QCPAxisTicker::generate(const QCPRange &range, const QLocale &locale, QChar formatChar, int precision, QVector<double> &ticks, QVector<double> *subTicks, QVector<QString> *tickLabels)
6183 {
6184  // generate (major) ticks:
6185  double tickStep = getTickStep(range);
6186  ticks = createTickVector(tickStep, range);
6187  trimTicks(range, ticks, true); // trim ticks to visible range plus one outer tick on each side (incase a subclass createTickVector creates more)
6188 
6189  // generate sub ticks between major ticks:
6190  if (subTicks)
6191  {
6192  if (!ticks.isEmpty())
6193  {
6194  *subTicks = createSubTickVector(getSubTickCount(tickStep), ticks);
6195  trimTicks(range, *subTicks, false);
6196  } else
6197  *subTicks = QVector<double>();
6198  }
6199 
6200  // finally trim also outliers (no further clipping happens in axis drawing):
6201  trimTicks(range, ticks, false);
6202  // generate labels for visible ticks if requested:
6203  if (tickLabels)
6204  *tickLabels = createLabelVector(ticks, locale, formatChar, precision);
6205 }
6206 
6218 {
6219  double exactStep = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers
6220  return cleanMantissa(exactStep);
6221 }
6222 
6231 {
6232  int result = 1; // default to 1, if no proper value can be found
6233 
6234  // separate integer and fractional part of mantissa:
6235  double epsilon = 0.01;
6236  double intPartf;
6237  int intPart;
6238  double fracPart = modf(getMantissa(tickStep), &intPartf);
6239  intPart = int(intPartf);
6240 
6241  // handle cases with (almost) integer mantissa:
6242  if (fracPart < epsilon || 1.0-fracPart < epsilon)
6243  {
6244  if (1.0-fracPart < epsilon)
6245  ++intPart;
6246  switch (intPart)
6247  {
6248  case 1: result = 4; break; // 1.0 -> 0.2 substep
6249  case 2: result = 3; break; // 2.0 -> 0.5 substep
6250  case 3: result = 2; break; // 3.0 -> 1.0 substep
6251  case 4: result = 3; break; // 4.0 -> 1.0 substep
6252  case 5: result = 4; break; // 5.0 -> 1.0 substep
6253  case 6: result = 2; break; // 6.0 -> 2.0 substep
6254  case 7: result = 6; break; // 7.0 -> 1.0 substep
6255  case 8: result = 3; break; // 8.0 -> 2.0 substep
6256  case 9: result = 2; break; // 9.0 -> 3.0 substep
6257  }
6258  } else
6259  {
6260  // handle cases with significantly fractional mantissa:
6261  if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa
6262  {
6263  switch (intPart)
6264  {
6265  case 1: result = 2; break; // 1.5 -> 0.5 substep
6266  case 2: result = 4; break; // 2.5 -> 0.5 substep
6267  case 3: result = 4; break; // 3.5 -> 0.7 substep
6268  case 4: result = 2; break; // 4.5 -> 1.5 substep
6269  case 5: result = 4; break; // 5.5 -> 1.1 substep (won't occur with default getTickStep from here on)
6270  case 6: result = 4; break; // 6.5 -> 1.3 substep
6271  case 7: result = 2; break; // 7.5 -> 2.5 substep
6272  case 8: result = 4; break; // 8.5 -> 1.7 substep
6273  case 9: result = 4; break; // 9.5 -> 1.9 substep
6274  }
6275  }
6276  // if mantissa fraction isn't 0.0 or 0.5, don't bother finding good sub tick marks, leave default
6277  }
6278 
6279  return result;
6280 }
6281 
6293 QString QCPAxisTicker::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision)
6294 {
6295  return locale.toString(tick, formatChar.toLatin1(), precision);
6296 }
6297 
6307 QVector<double> QCPAxisTicker::createSubTickVector(int subTickCount, const QVector<double> &ticks)
6308 {
6309  QVector<double> result;
6310  if (subTickCount <= 0 || ticks.size() < 2)
6311  return result;
6312 
6313  result.reserve((ticks.size()-1)*subTickCount);
6314  for (int i=1; i<ticks.size(); ++i)
6315  {
6316  double subTickStep = (ticks.at(i)-ticks.at(i-1))/double(subTickCount+1);
6317  for (int k=1; k<=subTickCount; ++k)
6318  result.append(ticks.at(i-1) + k*subTickStep);
6319  }
6320  return result;
6321 }
6322 
6338 QVector<double> QCPAxisTicker::createTickVector(double tickStep, const QCPRange &range)
6339 {
6340  QVector<double> result;
6341  // Generate tick positions according to tickStep:
6342  qint64 firstStep = qint64(floor((range.lower-mTickOrigin)/tickStep)); // do not use qFloor here, or we'll lose 64 bit precision
6343  qint64 lastStep = qint64(ceil((range.upper-mTickOrigin)/tickStep)); // do not use qCeil here, or we'll lose 64 bit precision
6344  int tickcount = int(lastStep-firstStep+1);
6345  if (tickcount < 0) tickcount = 0;
6346  result.resize(tickcount);
6347  for (int i=0; i<tickcount; ++i)
6348  result[i] = mTickOrigin + (firstStep+i)*tickStep;
6349  return result;
6350 }
6351 
6361 QVector<QString> QCPAxisTicker::createLabelVector(const QVector<double> &ticks, const QLocale &locale, QChar formatChar, int precision)
6362 {
6363  QVector<QString> result;
6364  result.reserve(ticks.size());
6365  foreach (double tickCoord, ticks)
6366  result.append(getTickLabel(tickCoord, locale, formatChar, precision));
6367  return result;
6368 }
6369 
6377 void QCPAxisTicker::trimTicks(const QCPRange &range, QVector<double> &ticks, bool keepOneOutlier) const
6378 {
6379  bool lowFound = false;
6380  bool highFound = false;
6381  int lowIndex = 0;
6382  int highIndex = -1;
6383 
6384  for (int i=0; i < ticks.size(); ++i)
6385  {
6386  if (ticks.at(i) >= range.lower)
6387  {
6388  lowFound = true;
6389  lowIndex = i;
6390  break;
6391  }
6392  }
6393  for (int i=ticks.size()-1; i >= 0; --i)
6394  {
6395  if (ticks.at(i) <= range.upper)
6396  {
6397  highFound = true;
6398  highIndex = i;
6399  break;
6400  }
6401  }
6402 
6403  if (highFound && lowFound)
6404  {
6405  int trimFront = qMax(0, lowIndex-(keepOneOutlier ? 1 : 0));
6406  int trimBack = qMax(0, ticks.size()-(keepOneOutlier ? 2 : 1)-highIndex);
6407  if (trimFront > 0 || trimBack > 0)
6408  ticks = ticks.mid(trimFront, ticks.size()-trimFront-trimBack);
6409  } else // all ticks are either all below or all above the range
6410  ticks.clear();
6411 }
6412 
6419 double QCPAxisTicker::pickClosest(double target, const QVector<double> &candidates) const
6420 {
6421  if (candidates.size() == 1)
6422  return candidates.first();
6423  QVector<double>::const_iterator it = std::lower_bound(candidates.constBegin(), candidates.constEnd(), target);
6424  if (it == candidates.constEnd())
6425  return *(it-1);
6426  else if (it == candidates.constBegin())
6427  return *it;
6428  else
6429  return target-*(it-1) < *it-target ? *(it-1) : *it;
6430 }
6431 
6439 double QCPAxisTicker::getMantissa(double input, double *magnitude) const
6440 {
6441  const double mag = qPow(10.0, qFloor(qLn(input)/qLn(10.0)));
6442  if (magnitude) *magnitude = mag;
6443  return input/mag;
6444 }
6445 
6452 double QCPAxisTicker::cleanMantissa(double input) const
6453 {
6454  double magnitude;
6455  const double mantissa = getMantissa(input, &magnitude);
6456  switch (mTickStepStrategy)
6457  {
6458  case tssReadability:
6459  {
6460  return pickClosest(mantissa, QVector<double>() << 1.0 << 2.0 << 2.5 << 5.0 << 10.0)*magnitude;
6461  }
6462  case tssMeetTickCount:
6463  {
6464  // this gives effectively a mantissa of 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 8.0, 10.0
6465  if (mantissa <= 5.0)
6466  return int(mantissa*2)/2.0*magnitude; // round digit after decimal point to 0.5
6467  else
6468  return int(mantissa/2.0)*2.0*magnitude; // round to first digit in multiples of 2
6469  }
6470  }
6471  return input;
6472 }
6473 /* end of 'src/axis/axisticker.cpp' */
6474 
6475 
6476 /* including file 'src/axis/axistickerdatetime.cpp' */
6477 /* modified 2021-03-29T02:30:44, size 18829 */
6478 
6482 
6524  mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")),
6525  mDateTimeSpec(Qt::LocalTime),
6526  mDateStrategy(dsNone)
6527 {
6528  setTickCount(4);
6529 }
6530 
6568 void QCPAxisTickerDateTime::setDateTimeFormat(const QString &format)
6569 {
6570  mDateTimeFormat = format;
6571 }
6572 
6587 {
6588  mDateTimeSpec = spec;
6589 }
6590 
6591 # if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
6592 
6598 void QCPAxisTickerDateTime::setTimeZone(const QTimeZone &zone)
6599 {
6600  mTimeZone = zone;
6601  mDateTimeSpec = Qt::TimeZone;
6602 }
6603 #endif
6604 
6615 {
6617 }
6618 
6626 void QCPAxisTickerDateTime::setTickOrigin(const QDateTime &origin)
6627 {
6628  setTickOrigin(dateTimeToKey(origin));
6629 }
6630 
6645 {
6646  double result = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers
6647 
6648  mDateStrategy = dsNone; // leaving it at dsNone means tick coordinates will not be tuned in any special way in createTickVector
6649  if (result < 1) // ideal tick step is below 1 second -> use normal clean mantissa algorithm in units of seconds
6650  {
6651  result = cleanMantissa(result);
6652  } else if (result < 86400*30.4375*12) // below a year
6653  {
6654  result = pickClosest(result, QVector<double>()
6655  << 1 << 2.5 << 5 << 10 << 15 << 30 << 60 << 2.5*60 << 5*60 << 10*60 << 15*60 << 30*60 << 60*60 // second, minute, hour range
6656  << 3600*2 << 3600*3 << 3600*6 << 3600*12 << 3600*24 // hour to day range
6657  << 86400*2 << 86400*5 << 86400*7 << 86400*14 << 86400*30.4375 << 86400*30.4375*2 << 86400*30.4375*3 << 86400*30.4375*6 << 86400*30.4375*12); // day, week, month range (avg. days per month includes leap years)
6658  if (result > 86400*30.4375-1) // month tick intervals or larger
6660  else if (result > 3600*24-1) // day tick intervals or larger
6662  } else // more than a year, go back to normal clean mantissa algorithm but in units of years
6663  {
6664  const double secondsPerYear = 86400*30.4375*12; // average including leap years
6665  result = cleanMantissa(result/secondsPerYear)*secondsPerYear;
6667  }
6668  return result;
6669 }
6670 
6679 {
6680  int result = QCPAxisTicker::getSubTickCount(tickStep);
6681  switch (qRound(tickStep)) // hand chosen subticks for specific minute/hour/day/week/month range (as specified in getTickStep)
6682  {
6683  case 5*60: result = 4; break;
6684  case 10*60: result = 1; break;
6685  case 15*60: result = 2; break;
6686  case 30*60: result = 1; break;
6687  case 60*60: result = 3; break;
6688  case 3600*2: result = 3; break;
6689  case 3600*3: result = 2; break;
6690  case 3600*6: result = 1; break;
6691  case 3600*12: result = 3; break;
6692  case 3600*24: result = 3; break;
6693  case 86400*2: result = 1; break;
6694  case 86400*5: result = 4; break;
6695  case 86400*7: result = 6; break;
6696  case 86400*14: result = 1; break;
6697  case int(86400*30.4375+0.5): result = 3; break;
6698  case int(86400*30.4375*2+0.5): result = 1; break;
6699  case int(86400*30.4375*3+0.5): result = 2; break;
6700  case int(86400*30.4375*6+0.5): result = 5; break;
6701  case int(86400*30.4375*12+0.5): result = 3; break;
6702  }
6703  return result;
6704 }
6705 
6714 QString QCPAxisTickerDateTime::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision)
6715 {
6716  Q_UNUSED(precision)
6717  Q_UNUSED(formatChar)
6718 # if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
6719  if (mDateTimeSpec == Qt::TimeZone)
6720  return locale.toString(keyToDateTime(tick).toTimeZone(mTimeZone), mDateTimeFormat);
6721  else
6722  return locale.toString(keyToDateTime(tick).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
6723 # else
6724  return locale.toString(keyToDateTime(tick).toTimeSpec(mDateTimeSpec), mDateTimeFormat);
6725 # endif
6726 }
6727 
6735 QVector<double> QCPAxisTickerDateTime::createTickVector(double tickStep, const QCPRange &range)
6736 {
6737  QVector<double> result = QCPAxisTicker::createTickVector(tickStep, range);
6738  if (!result.isEmpty())
6739  {
6741  {
6742  QDateTime uniformDateTime = keyToDateTime(mTickOrigin); // the time of this datetime will be set for all other ticks, if possible
6743  QDateTime tickDateTime;
6744  for (int i=0; i<result.size(); ++i)
6745  {
6746  tickDateTime = keyToDateTime(result.at(i));
6747  tickDateTime.setTime(uniformDateTime.time());
6748  result[i] = dateTimeToKey(tickDateTime);
6749  }
6750  } else if (mDateStrategy == dsUniformDayInMonth)
6751  {
6752  QDateTime uniformDateTime = keyToDateTime(mTickOrigin); // this day (in month) and time will be set for all other ticks, if possible
6753  QDateTime tickDateTime;
6754  for (int i=0; i<result.size(); ++i)
6755  {
6756  tickDateTime = keyToDateTime(result.at(i));
6757  tickDateTime.setTime(uniformDateTime.time());
6758  int thisUniformDay = uniformDateTime.date().day() <= tickDateTime.date().daysInMonth() ? uniformDateTime.date().day() : tickDateTime.date().daysInMonth(); // don't exceed month (e.g. try to set day 31 in February)
6759  if (thisUniformDay-tickDateTime.date().day() < -15) // with leap years involved, date month may jump backwards or forwards, and needs to be corrected before setting day
6760  tickDateTime = tickDateTime.addMonths(1);
6761  else if (thisUniformDay-tickDateTime.date().day() > 15) // with leap years involved, date month may jump backwards or forwards, and needs to be corrected before setting day
6762  tickDateTime = tickDateTime.addMonths(-1);
6763  tickDateTime.setDate(QDate(tickDateTime.date().year(), tickDateTime.date().month(), thisUniformDay));
6764  result[i] = dateTimeToKey(tickDateTime);
6765  }
6766  }
6767  }
6768  return result;
6769 }
6770 
6781 {
6782 # if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
6783  return QDateTime::fromTime_t(key).addMSecs((key-(qint64)key)*1000);
6784 # else
6785  return QDateTime::fromMSecsSinceEpoch(qint64(key*1000.0));
6786 # endif
6787 }
6788 
6800 double QCPAxisTickerDateTime::dateTimeToKey(const QDateTime &dateTime)
6801 {
6802 # if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
6803  return dateTime.toTime_t()+dateTime.time().msec()/1000.0;
6804 # else
6805  return dateTime.toMSecsSinceEpoch()/1000.0;
6806 # endif
6807 }
6808 
6820 double QCPAxisTickerDateTime::dateTimeToKey(const QDate &date, Qt::TimeSpec timeSpec)
6821 {
6822 # if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
6823  return QDateTime(date, QTime(0, 0), timeSpec).toTime_t();
6824 # elif QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
6825  return QDateTime(date, QTime(0, 0), timeSpec).toMSecsSinceEpoch()/1000.0;
6826 # else
6827  return date.startOfDay(timeSpec).toMSecsSinceEpoch()/1000.0;
6828 # endif
6829 }
6830 /* end of 'src/axis/axistickerdatetime.cpp' */
6831 
6832 
6833 /* including file 'src/axis/axistickertime.cpp' */
6834 /* modified 2021-03-29T02:30:44, size 11745 */
6835 
6839 
6880  mTimeFormat(QLatin1String("%h:%m:%s")),
6881  mSmallestUnit(tuSeconds),
6882  mBiggestUnit(tuHours)
6883 {
6884  setTickCount(4);
6886  mFieldWidth[tuSeconds] = 2;
6887  mFieldWidth[tuMinutes] = 2;
6888  mFieldWidth[tuHours] = 2;
6889  mFieldWidth[tuDays] = 1;
6890 
6891  mFormatPattern[tuMilliseconds] = QLatin1String("%z");
6892  mFormatPattern[tuSeconds] = QLatin1String("%s");
6893  mFormatPattern[tuMinutes] = QLatin1String("%m");
6894  mFormatPattern[tuHours] = QLatin1String("%h");
6895  mFormatPattern[tuDays] = QLatin1String("%d");
6896 }
6897 
6916 void QCPAxisTickerTime::setTimeFormat(const QString &format)
6917 {
6918  mTimeFormat = format;
6919 
6920  // determine smallest and biggest unit in format, to optimize unit replacement and allow biggest
6921  // unit to consume remaining time of a tick value and grow beyond its modulo (e.g. min > 59)
6924  bool hasSmallest = false;
6925  for (int i = tuMilliseconds; i <= tuDays; ++i)
6926  {
6927  TimeUnit unit = static_cast<TimeUnit>(i);
6928  if (mTimeFormat.contains(mFormatPattern.value(unit)))
6929  {
6930  if (!hasSmallest)
6931  {
6932  mSmallestUnit = unit;
6933  hasSmallest = true;
6934  }
6935  mBiggestUnit = unit;
6936  }
6937  }
6938 }
6939 
6948 {
6949  mFieldWidth[unit] = qMax(width, 1);
6950 }
6951 
6962 {
6963  double result = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers
6964 
6965  if (result < 1) // ideal tick step is below 1 second -> use normal clean mantissa algorithm in units of seconds
6966  {
6968  result = qMax(cleanMantissa(result), 0.001); // smallest tick step is 1 millisecond
6969  else // have no milliseconds available in format, so stick with 1 second tickstep
6970  result = 1.0;
6971  } else if (result < 3600*24) // below a day
6972  {
6973  // the filling of availableSteps seems a bit contorted but it fills in a sorted fashion and thus saves a post-fill sorting run
6974  QVector<double> availableSteps;
6975  // seconds range:
6976  if (mSmallestUnit <= tuSeconds)
6977  availableSteps << 1;
6979  availableSteps << 2.5; // only allow half second steps if milliseconds are there to display it
6980  else if (mSmallestUnit == tuSeconds)
6981  availableSteps << 2;
6982  if (mSmallestUnit <= tuSeconds)
6983  availableSteps << 5 << 10 << 15 << 30;
6984  // minutes range:
6985  if (mSmallestUnit <= tuMinutes)
6986  availableSteps << 1*60;
6987  if (mSmallestUnit <= tuSeconds)
6988  availableSteps << 2.5*60; // only allow half minute steps if seconds are there to display it
6989  else if (mSmallestUnit == tuMinutes)
6990  availableSteps << 2*60;
6991  if (mSmallestUnit <= tuMinutes)
6992  availableSteps << 5*60 << 10*60 << 15*60 << 30*60;
6993  // hours range:
6994  if (mSmallestUnit <= tuHours)
6995  availableSteps << 1*3600 << 2*3600 << 3*3600 << 6*3600 << 12*3600 << 24*3600;
6996  // pick available step that is most appropriate to approximate ideal step:
6997  result = pickClosest(result, availableSteps);
6998  } else // more than a day, go back to normal clean mantissa algorithm but in units of days
6999  {
7000  const double secondsPerDay = 3600*24;
7001  result = cleanMantissa(result/secondsPerDay)*secondsPerDay;
7002  }
7003  return result;
7004 }
7005 
7013 {
7014  int result = QCPAxisTicker::getSubTickCount(tickStep);
7015  switch (qRound(tickStep)) // hand chosen subticks for specific minute/hour/day range (as specified in getTickStep)
7016  {
7017  case 5*60: result = 4; break;
7018  case 10*60: result = 1; break;
7019  case 15*60: result = 2; break;
7020  case 30*60: result = 1; break;
7021  case 60*60: result = 3; break;
7022  case 3600*2: result = 3; break;
7023  case 3600*3: result = 2; break;
7024  case 3600*6: result = 1; break;
7025  case 3600*12: result = 3; break;
7026  case 3600*24: result = 3; break;
7027  }
7028  return result;
7029 }
7030 
7038 QString QCPAxisTickerTime::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision)
7039 {
7040  Q_UNUSED(precision)
7041  Q_UNUSED(formatChar)
7042  Q_UNUSED(locale)
7043  bool negative = tick < 0;
7044  if (negative) tick *= -1;
7045  double values[tuDays+1]; // contains the msec/sec/min/... value with its respective modulo (e.g. minute 0..59)
7046  double restValues[tuDays+1]; // contains the msec/sec/min/... value as if it's the largest available unit and thus consumes the remaining time
7047 
7048  restValues[tuMilliseconds] = tick*1000;
7049  values[tuMilliseconds] = modf(restValues[tuMilliseconds]/1000, &restValues[tuSeconds])*1000;
7050  values[tuSeconds] = modf(restValues[tuSeconds]/60, &restValues[tuMinutes])*60;
7051  values[tuMinutes] = modf(restValues[tuMinutes]/60, &restValues[tuHours])*60;
7052  values[tuHours] = modf(restValues[tuHours]/24, &restValues[tuDays])*24;
7053  // no need to set values[tuDays] because days are always a rest value (there is no higher unit so it consumes all remaining time)
7054 
7055  QString result = mTimeFormat;
7056  for (int i = mSmallestUnit; i <= mBiggestUnit; ++i)
7057  {
7058  TimeUnit iUnit = static_cast<TimeUnit>(i);
7059  replaceUnit(result, iUnit, qRound(iUnit == mBiggestUnit ? restValues[iUnit] : values[iUnit]));
7060  }
7061  if (negative)
7062  result.prepend(QLatin1Char('-'));
7063  return result;
7064 }
7065 
7071 void QCPAxisTickerTime::replaceUnit(QString &text, QCPAxisTickerTime::TimeUnit unit, int value) const
7072 {
7073  QString valueStr = QString::number(value);
7074  while (valueStr.size() < mFieldWidth.value(unit))
7075  valueStr.prepend(QLatin1Char('0'));
7076 
7077  text.replace(mFormatPattern.value(unit), valueStr);
7078 }
7079 /* end of 'src/axis/axistickertime.cpp' */
7080 
7081 
7082 /* including file 'src/axis/axistickerfixed.cpp' */
7083 /* modified 2021-03-29T02:30:44, size 5575 */
7084 
7088 
7113  mTickStep(1.0),
7114  mScaleStrategy(ssNone)
7115 {
7116 }
7117 
7128 {
7129  if (step > 0)
7130  mTickStep = step;
7131  else
7132  qDebug() << Q_FUNC_INFO << "tick step must be greater than zero:" << step;
7133 }
7134 
7143 {
7144  mScaleStrategy = strategy;
7145 }
7146 
7158 {
7159  switch (mScaleStrategy)
7160  {
7161  case ssNone:
7162  {
7163  return mTickStep;
7164  }
7165  case ssMultiples:
7166  {
7167  double exactStep = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers
7168  if (exactStep < mTickStep)
7169  return mTickStep;
7170  else
7171  return qint64(cleanMantissa(exactStep/mTickStep)+0.5)*mTickStep;
7172  }
7173  case ssPowers:
7174  {
7175  double exactStep = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers
7176  return qPow(mTickStep, int(qLn(exactStep)/qLn(mTickStep)+0.5));
7177  }
7178  }
7179  return mTickStep;
7180 }
7181 /* end of 'src/axis/axistickerfixed.cpp' */
7182 
7183 
7184 /* including file 'src/axis/axistickertext.cpp' */
7185 /* modified 2021-03-29T02:30:44, size 8742 */
7186 
7190 
7210 /* start of documentation of inline functions */
7211 
7221 /* end of documentation of inline functions */
7222 
7228  mSubTickCount(0)
7229 {
7230 }
7231 
7242 void QCPAxisTickerText::setTicks(const QMap<double, QString> &ticks)
7243 {
7244  mTicks = ticks;
7245 }
7246 
7255 void QCPAxisTickerText::setTicks(const QVector<double> &positions, const QVector<QString> &labels)
7256 {
7257  clear();
7258  addTicks(positions, labels);
7259 }
7260 
7267 {
7268  if (subTicks >= 0)
7269  mSubTickCount = subTicks;
7270  else
7271  qDebug() << Q_FUNC_INFO << "sub tick count can't be negative:" << subTicks;
7272 }
7273 
7283 {
7284  mTicks.clear();
7285 }
7286 
7293 void QCPAxisTickerText::addTick(double position, const QString &label)
7294 {
7295  mTicks.insert(position, label);
7296 }
7297 
7308 void QCPAxisTickerText::addTicks(const QMap<double, QString> &ticks)
7309 {
7310 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
7311  mTicks.unite(ticks);
7312 #else
7313  mTicks.insert(ticks);
7314 #endif
7315 }
7316 
7328 void QCPAxisTickerText::addTicks(const QVector<double> &positions, const QVector<QString> &labels)
7329 {
7330  if (positions.size() != labels.size())
7331  qDebug() << Q_FUNC_INFO << "passed unequal length vectors for positions and labels:" << positions.size() << labels.size();
7332  int n = qMin(positions.size(), labels.size());
7333  for (int i=0; i<n; ++i)
7334  mTicks.insert(positions.at(i), labels.at(i));
7335 }
7336 
7343 {
7344  // text axis ticker has manual tick positions, so doesn't need this method
7345  Q_UNUSED(range)
7346  return 1.0;
7347 }
7348 
7355 {
7356  Q_UNUSED(tickStep)
7357  return mSubTickCount;
7358 }
7359 
7366 QString QCPAxisTickerText::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision)
7367 {
7368  Q_UNUSED(locale)
7369  Q_UNUSED(formatChar)
7370  Q_UNUSED(precision)
7371  return mTicks.value(tick);
7372 }
7373 
7381 QVector<double> QCPAxisTickerText::createTickVector(double tickStep, const QCPRange &range)
7382 {
7383  Q_UNUSED(tickStep)
7384  QVector<double> result;
7385  if (mTicks.isEmpty())
7386  return result;
7387 
7388  QMap<double, QString>::const_iterator start = mTicks.lowerBound(range.lower);
7389  QMap<double, QString>::const_iterator end = mTicks.upperBound(range.upper);
7390  // this method should try to give one tick outside of range so proper subticks can be generated:
7391  if (start != mTicks.constBegin()) --start;
7392  if (end != mTicks.constEnd()) ++end;
7393  for (QMap<double, QString>::const_iterator it = start; it != end; ++it)
7394  result.append(it.key());
7395 
7396  return result;
7397 }
7398 /* end of 'src/axis/axistickertext.cpp' */
7399 
7400 
7401 /* including file 'src/axis/axistickerpi.cpp' */
7402 /* modified 2021-03-29T02:30:44, size 11177 */
7403 
7407 
7428  mPiSymbol(QLatin1String(" ")+QChar(0x03C0)),
7429  mPiValue(M_PI),
7430  mPeriodicity(0),
7431  mFractionStyle(fsUnicodeFractions),
7432  mPiTickStep(0)
7433 {
7434  setTickCount(4);
7435 }
7436 
7444 void QCPAxisTickerPi::setPiSymbol(QString symbol)
7445 {
7446  mPiSymbol = symbol;
7447 }
7448 
7456 {
7457  mPiValue = pi;
7458 }
7459 
7468 void QCPAxisTickerPi::setPeriodicity(int multiplesOfPi)
7469 {
7470  mPeriodicity = qAbs(multiplesOfPi);
7471 }
7472 
7478 {
7479  mFractionStyle = style;
7480 }
7481 
7491 {
7492  mPiTickStep = range.size()/mPiValue/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers
7494  return mPiTickStep*mPiValue;
7495 }
7496 
7506 {
7507  return QCPAxisTicker::getSubTickCount(tickStep/mPiValue);
7508 }
7509 
7518 QString QCPAxisTickerPi::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision)
7519 {
7520  double tickInPis = tick/mPiValue;
7521  if (mPeriodicity > 0)
7522  tickInPis = fmod(tickInPis, mPeriodicity);
7523 
7524  if (mFractionStyle != fsFloatingPoint && mPiTickStep > 0.09 && mPiTickStep < 50)
7525  {
7526  // simply construct fraction from decimal like 1.234 -> 1234/1000 and then simplify fraction, smaller digits are irrelevant due to mPiTickStep conditional above
7527  int denominator = 1000;
7528  int numerator = qRound(tickInPis*denominator);
7529  simplifyFraction(numerator, denominator);
7530  if (qAbs(numerator) == 1 && denominator == 1)
7531  return (numerator < 0 ? QLatin1String("-") : QLatin1String("")) + mPiSymbol.trimmed();
7532  else if (numerator == 0)
7533  return QLatin1String("0");
7534  else
7535  return fractionToString(numerator, denominator) + mPiSymbol;
7536  } else
7537  {
7538  if (qFuzzyIsNull(tickInPis))
7539  return QLatin1String("0");
7540  else if (qFuzzyCompare(qAbs(tickInPis), 1.0))
7541  return (tickInPis < 0 ? QLatin1String("-") : QLatin1String("")) + mPiSymbol.trimmed();
7542  else
7543  return QCPAxisTicker::getTickLabel(tickInPis, locale, formatChar, precision) + mPiSymbol;
7544  }
7545 }
7546 
7553 void QCPAxisTickerPi::simplifyFraction(int &numerator, int &denominator) const
7554 {
7555  if (numerator == 0 || denominator == 0)
7556  return;
7557 
7558  int num = numerator;
7559  int denom = denominator;
7560  while (denom != 0) // euclidean gcd algorithm
7561  {
7562  int oldDenom = denom;
7563  denom = num % denom;
7564  num = oldDenom;
7565  }
7566  // num is now gcd of numerator and denominator
7567  numerator /= num;
7568  denominator /= num;
7569 }
7570 
7580 QString QCPAxisTickerPi::fractionToString(int numerator, int denominator) const
7581 {
7582  if (denominator == 0)
7583  {
7584  qDebug() << Q_FUNC_INFO << "called with zero denominator";
7585  return QString();
7586  }
7587  if (mFractionStyle == fsFloatingPoint) // should never be the case when calling this function
7588  {
7589  qDebug() << Q_FUNC_INFO << "shouldn't be called with fraction style fsDecimal";
7590  return QString::number(numerator/double(denominator)); // failsafe
7591  }
7592  int sign = numerator*denominator < 0 ? -1 : 1;
7593  numerator = qAbs(numerator);
7594  denominator = qAbs(denominator);
7595 
7596  if (denominator == 1)
7597  {
7598  return QString::number(sign*numerator);
7599  } else
7600  {
7601  int integerPart = numerator/denominator;
7602  int remainder = numerator%denominator;
7603  if (remainder == 0)
7604  {
7605  return QString::number(sign*integerPart);
7606  } else
7607  {
7609  {
7610  return QString(QLatin1String("%1%2%3/%4"))
7611  .arg(sign == -1 ? QLatin1String("-") : QLatin1String(""))
7612  .arg(integerPart > 0 ? QString::number(integerPart)+QLatin1String(" ") : QString(QLatin1String("")))
7613  .arg(remainder)
7614  .arg(denominator);
7615  } else if (mFractionStyle == fsUnicodeFractions)
7616  {
7617  return QString(QLatin1String("%1%2%3"))
7618  .arg(sign == -1 ? QLatin1String("-") : QLatin1String(""))
7619  .arg(integerPart > 0 ? QString::number(integerPart) : QLatin1String(""))
7620  .arg(unicodeFraction(remainder, denominator));
7621  }
7622  }
7623  }
7624  return QString();
7625 }
7626 
7636 QString QCPAxisTickerPi::unicodeFraction(int numerator, int denominator) const
7637 {
7638  return unicodeSuperscript(numerator)+QChar(0x2044)+unicodeSubscript(denominator);
7639 }
7640 
7646 QString QCPAxisTickerPi::unicodeSuperscript(int number) const
7647 {
7648  if (number == 0)
7649  return QString(QChar(0x2070));
7650 
7651  QString result;
7652  while (number > 0)
7653  {
7654  const int digit = number%10;
7655  switch (digit)
7656  {
7657  case 1: { result.prepend(QChar(0x00B9)); break; }
7658  case 2: { result.prepend(QChar(0x00B2)); break; }
7659  case 3: { result.prepend(QChar(0x00B3)); break; }
7660  default: { result.prepend(QChar(0x2070+digit)); break; }
7661  }
7662  number /= 10;
7663  }
7664  return result;
7665 }
7666 
7672 QString QCPAxisTickerPi::unicodeSubscript(int number) const
7673 {
7674  if (number == 0)
7675  return QString(QChar(0x2080));
7676 
7677  QString result;
7678  while (number > 0)
7679  {
7680  result.prepend(QChar(0x2080+number%10));
7681  number /= 10;
7682  }
7683  return result;
7684 }
7685 /* end of 'src/axis/axistickerpi.cpp' */
7686 
7687 
7688 /* including file 'src/axis/axistickerlog.cpp' */
7689 /* modified 2021-03-29T02:30:44, size 7890 */
7690 
7694 
7725  mLogBase(10.0),
7726  mSubTickCount(8), // generates 10 intervals
7727  mLogBaseLnInv(1.0/qLn(mLogBase))
7728 {
7729 }
7730 
7736 {
7737  if (base > 0)
7738  {
7739  mLogBase = base;
7740  mLogBaseLnInv = 1.0/qLn(mLogBase);
7741  } else
7742  qDebug() << Q_FUNC_INFO << "log base has to be greater than zero:" << base;
7743 }
7744 
7756 {
7757  if (subTicks >= 0)
7758  mSubTickCount = subTicks;
7759  else
7760  qDebug() << Q_FUNC_INFO << "sub tick count can't be negative:" << subTicks;
7761 }
7762 
7771 {
7772  Q_UNUSED(tickStep)
7773  return mSubTickCount;
7774 }
7775 
7788 QVector<double> QCPAxisTickerLog::createTickVector(double tickStep, const QCPRange &range)
7789 {
7790  QVector<double> result;
7791  if (range.lower > 0 && range.upper > 0) // positive range
7792  {
7793  const double baseTickCount = qLn(range.upper/range.lower)*mLogBaseLnInv;
7794  if (baseTickCount < 1.6) // if too few log ticks would be visible in axis range, fall back to regular tick vector generation
7795  return QCPAxisTicker::createTickVector(tickStep, range);
7796  const double exactPowerStep = baseTickCount/double(mTickCount+1e-10);
7797  const double newLogBase = qPow(mLogBase, qMax(int(cleanMantissa(exactPowerStep)), 1));
7798  double currentTick = qPow(newLogBase, qFloor(qLn(range.lower)/qLn(newLogBase)));
7799  result.append(currentTick);
7800  while (currentTick < range.upper && currentTick > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
7801  {
7802  currentTick *= newLogBase;
7803  result.append(currentTick);
7804  }
7805  } else if (range.lower < 0 && range.upper < 0) // negative range
7806  {
7807  const double baseTickCount = qLn(range.lower/range.upper)*mLogBaseLnInv;
7808  if (baseTickCount < 1.6) // if too few log ticks would be visible in axis range, fall back to regular tick vector generation
7809  return QCPAxisTicker::createTickVector(tickStep, range);
7810  const double exactPowerStep = baseTickCount/double(mTickCount+1e-10);
7811  const double newLogBase = qPow(mLogBase, qMax(int(cleanMantissa(exactPowerStep)), 1));
7812  double currentTick = -qPow(newLogBase, qCeil(qLn(-range.lower)/qLn(newLogBase)));
7813  result.append(currentTick);
7814  while (currentTick < range.upper && currentTick < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case
7815  {
7816  currentTick /= newLogBase;
7817  result.append(currentTick);
7818  }
7819  } else // invalid range for logarithmic scale, because lower and upper have different sign
7820  {
7821  qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << range.lower << ".." << range.upper;
7822  }
7823 
7824  return result;
7825 }
7826 /* end of 'src/axis/axistickerlog.cpp' */
7827 
7828 
7829 /* including file 'src/axis/axis.cpp' */
7830 /* modified 2021-03-29T02:30:44, size 99883 */
7831 
7832 
7836 
7856  QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
7857  mSubGridVisible{},
7858  mAntialiasedSubGrid{},
7859  mAntialiasedZeroLine{},
7860  mParentAxis(parentAxis)
7861 {
7862  // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called
7863  setParent(parentAxis);
7864  setPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
7865  setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
7866  setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine));
7867  setSubGridVisible(false);
7868  setAntialiased(false);
7869  setAntialiasedSubGrid(false);
7870  setAntialiasedZeroLine(false);
7871 }
7872 
7878 void QCPGrid::setSubGridVisible(bool visible)
7879 {
7881 }
7882 
7887 {
7888  mAntialiasedSubGrid = enabled;
7889 }
7890 
7895 {
7896  mAntialiasedZeroLine = enabled;
7897 }
7898 
7902 void QCPGrid::setPen(const QPen &pen)
7903 {
7904  mPen = pen;
7905 }
7906 
7910 void QCPGrid::setSubGridPen(const QPen &pen)
7911 {
7912  mSubGridPen = pen;
7913 }
7914 
7921 void QCPGrid::setZeroLinePen(const QPen &pen)
7922 {
7923  mZeroLinePen = pen;
7924 }
7925 
7940 {
7942 }
7943 
7950 {
7951  if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
7952 
7954  drawSubGridLines(painter);
7955  drawGridLines(painter);
7956 }
7957 
7965 {
7966  if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
7967 
7968  const int tickCount = mParentAxis->mTickVector.size();
7969  double t; // helper variable, result of coordinate-to-pixel transforms
7970  if (mParentAxis->orientation() == Qt::Horizontal)
7971  {
7972  // draw zeroline:
7973  int zeroLineIndex = -1;
7974  if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
7975  {
7977  painter->setPen(mZeroLinePen);
7978  double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero
7979  for (int i=0; i<tickCount; ++i)
7980  {
7981  if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
7982  {
7983  zeroLineIndex = i;
7984  t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
7985  painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
7986  break;
7987  }
7988  }
7989  }
7990  // draw grid lines:
7992  painter->setPen(mPen);
7993  for (int i=0; i<tickCount; ++i)
7994  {
7995  if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
7996  t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x
7997  painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
7998  }
7999  } else
8000  {
8001  // draw zeroline:
8002  int zeroLineIndex = -1;
8003  if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0)
8004  {
8006  painter->setPen(mZeroLinePen);
8007  double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero
8008  for (int i=0; i<tickCount; ++i)
8009  {
8010  if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon)
8011  {
8012  zeroLineIndex = i;
8013  t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
8014  painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
8015  break;
8016  }
8017  }
8018  }
8019  // draw grid lines:
8021  painter->setPen(mPen);
8022  for (int i=0; i<tickCount; ++i)
8023  {
8024  if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline
8025  t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y
8026  painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
8027  }
8028  }
8029 }
8030 
8038 {
8039  if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
8040 
8042  double t; // helper variable, result of coordinate-to-pixel transforms
8043  painter->setPen(mSubGridPen);
8044  if (mParentAxis->orientation() == Qt::Horizontal)
8045  {
8046  foreach (double tickCoord, mParentAxis->mSubTickVector)
8047  {
8048  t = mParentAxis->coordToPixel(tickCoord); // x
8049  painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top()));
8050  }
8051  } else
8052  {
8053  foreach (double tickCoord, mParentAxis->mSubTickVector)
8054  {
8055  t = mParentAxis->coordToPixel(tickCoord); // y
8056  painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t));
8057  }
8058  }
8059 }
8060 
8061 
8065 
8088 /* start of documentation of inline functions */
8089 
8146 /* end of documentation of inline functions */
8147 /* start of documentation of signals */
8148 
8187 /* end of documentation of signals */
8188 
8197  QCPLayerable(parent->parentPlot(), QString(), parent),
8198  // axis base:
8199  mAxisType(type),
8200  mAxisRect(parent),
8201  mPadding(5),
8202  mOrientation(orientation(type)),
8203  mSelectableParts(spAxis | spTickLabels | spAxisLabel),
8204  mSelectedParts(spNone),
8205  mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
8206  mSelectedBasePen(QPen(Qt::blue, 2)),
8207  // axis label:
8208  mLabel(),
8209  mLabelFont(mParentPlot->font()),
8210  mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
8211  mLabelColor(Qt::black),
8212  mSelectedLabelColor(Qt::blue),
8213  // tick labels:
8214  mTickLabels(true),
8215  mTickLabelFont(mParentPlot->font()),
8216  mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
8217  mTickLabelColor(Qt::black),
8218  mSelectedTickLabelColor(Qt::blue),
8219  mNumberPrecision(6),
8220  mNumberFormatChar('g'),
8221  mNumberBeautifulPowers(true),
8222  // ticks and subticks:
8223  mTicks(true),
8224  mSubTicks(true),
8225  mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
8226  mSelectedTickPen(QPen(Qt::blue, 2)),
8227  mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
8228  mSelectedSubTickPen(QPen(Qt::blue, 2)),
8229  // scale and range:
8230  mRange(0, 5),
8231  mRangeReversed(false),
8232  mScaleType(stLinear),
8233  // internal members:
8234  mGrid(new QCPGrid(this)),
8235  mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())),
8236  mTicker(new QCPAxisTicker),
8237  mCachedMarginValid(false),
8238  mCachedMargin(0),
8239  mDragging(false)
8240 {
8241  setParent(parent);
8242  mGrid->setVisible(false);
8243  setAntialiased(false);
8244  setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again
8245 
8246  if (type == atTop)
8247  {
8249  setLabelPadding(6);
8250  } else if (type == atRight)
8251  {
8253  setLabelPadding(12);
8254  } else if (type == atBottom)
8255  {
8257  setLabelPadding(3);
8258  } else if (type == atLeft)
8259  {
8261  setLabelPadding(10);
8262  }
8263 }
8264 
8266 {
8267  delete mAxisPainter;
8268  delete mGrid; // delete grid here instead of via parent ~QObject for better defined deletion order
8269 }
8270 
8271 /* No documentation as it is a property getter */
8273 {
8275 }
8276 
8277 /* No documentation as it is a property getter */
8279 {
8281 }
8282 
8283 /* No documentation as it is a property getter */
8285 {
8286  return mAxisPainter->tickLabelSide;
8287 }
8288 
8289 /* No documentation as it is a property getter */
8290 QString QCPAxis::numberFormat() const
8291 {
8292  QString result;
8293  result.append(mNumberFormatChar);
8295  {
8296  result.append(QLatin1Char('b'));
8298  result.append(QLatin1Char('c'));
8299  }
8300  return result;
8301 }
8302 
8303 /* No documentation as it is a property getter */
8305 {
8306  return mAxisPainter->tickLengthIn;
8307 }
8308 
8309 /* No documentation as it is a property getter */
8311 {
8312  return mAxisPainter->tickLengthOut;
8313 }
8314 
8315 /* No documentation as it is a property getter */
8317 {
8318  return mAxisPainter->subTickLengthIn;
8319 }
8320 
8321 /* No documentation as it is a property getter */
8323 {
8325 }
8326 
8327 /* No documentation as it is a property getter */
8329 {
8330  return mAxisPainter->labelPadding;
8331 }
8332 
8333 /* No documentation as it is a property getter */
8334 int QCPAxis::offset() const
8335 {
8336  return mAxisPainter->offset;
8337 }
8338 
8339 /* No documentation as it is a property getter */
8341 {
8342  return mAxisPainter->lowerEnding;
8343 }
8344 
8345 /* No documentation as it is a property getter */
8347 {
8348  return mAxisPainter->upperEnding;
8349 }
8350 
8366 {
8367  if (mScaleType != type)
8368  {
8369  mScaleType = type;
8370  if (mScaleType == stLogarithmic)
8372  mCachedMarginValid = false;
8374  }
8375 }
8376 
8385 void QCPAxis::setRange(const QCPRange &range)
8386 {
8387  if (range.lower == mRange.lower && range.upper == mRange.upper)
8388  return;
8389 
8390  if (!QCPRange::validRange(range)) return;
8391  QCPRange oldRange = mRange;
8392  if (mScaleType == stLogarithmic)
8393  {
8395  } else
8396  {
8398  }
8399  emit rangeChanged(mRange);
8400  emit rangeChanged(mRange, oldRange);
8401 }
8402 
8413 void QCPAxis::setSelectableParts(const SelectableParts &selectable)
8414 {
8415  if (mSelectableParts != selectable)
8416  {
8417  mSelectableParts = selectable;
8419  }
8420 }
8421 
8437 void QCPAxis::setSelectedParts(const SelectableParts &selected)
8438 {
8439  if (mSelectedParts != selected)
8440  {
8441  mSelectedParts = selected;
8443  }
8444 }
8445 
8455 void QCPAxis::setRange(double lower, double upper)
8456 {
8457  if (lower == mRange.lower && upper == mRange.upper)
8458  return;
8459 
8460  if (!QCPRange::validRange(lower, upper)) return;
8461  QCPRange oldRange = mRange;
8462  mRange.lower = lower;
8463  mRange.upper = upper;
8464  if (mScaleType == stLogarithmic)
8465  {
8467  } else
8468  {
8470  }
8471  emit rangeChanged(mRange);
8472  emit rangeChanged(mRange, oldRange);
8473 }
8474 
8486 void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment)
8487 {
8488  if (alignment == Qt::AlignLeft)
8489  setRange(position, position+size);
8490  else if (alignment == Qt::AlignRight)
8491  setRange(position-size, position);
8492  else // alignment == Qt::AlignCenter
8493  setRange(position-size/2.0, position+size/2.0);
8494 }
8495 
8500 void QCPAxis::setRangeLower(double lower)
8501 {
8502  if (mRange.lower == lower)
8503  return;
8504 
8505  QCPRange oldRange = mRange;
8506  mRange.lower = lower;
8507  if (mScaleType == stLogarithmic)
8508  {
8510  } else
8511  {
8513  }
8514  emit rangeChanged(mRange);
8515  emit rangeChanged(mRange, oldRange);
8516 }
8517 
8522 void QCPAxis::setRangeUpper(double upper)
8523 {
8524  if (mRange.upper == upper)
8525  return;
8526 
8527  QCPRange oldRange = mRange;
8528  mRange.upper = upper;
8529  if (mScaleType == stLogarithmic)
8530  {
8532  } else
8533  {
8535  }
8536  emit rangeChanged(mRange);
8537  emit rangeChanged(mRange, oldRange);
8538 }
8539 
8549 void QCPAxis::setRangeReversed(bool reversed)
8550 {
8551  mRangeReversed = reversed;
8552 }
8553 
8567 void QCPAxis::setTicker(QSharedPointer<QCPAxisTicker> ticker)
8568 {
8569  if (ticker)
8570  mTicker = ticker;
8571  else
8572  qDebug() << Q_FUNC_INFO << "can not set nullptr as axis ticker";
8573  // no need to invalidate margin cache here because produced tick labels are checked for changes in setupTickVector
8574 }
8575 
8584 void QCPAxis::setTicks(bool show)
8585 {
8586  if (mTicks != show)
8587  {
8588  mTicks = show;
8589  mCachedMarginValid = false;
8590  }
8591 }
8592 
8596 void QCPAxis::setTickLabels(bool show)
8597 {
8598  if (mTickLabels != show)
8599  {
8600  mTickLabels = show;
8601  mCachedMarginValid = false;
8602  if (!mTickLabels)
8603  mTickVectorLabels.clear();
8604  }
8605 }
8606 
8612 {
8614  {
8616  mCachedMarginValid = false;
8617  }
8618 }
8619 
8625 void QCPAxis::setTickLabelFont(const QFont &font)
8626 {
8627  if (font != mTickLabelFont)
8628  {
8629  mTickLabelFont = font;
8630  mCachedMarginValid = false;
8631  }
8632 }
8633 
8640 {
8642 }
8643 
8653 void QCPAxis::setTickLabelRotation(double degrees)
8654 {
8655  if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation))
8656  {
8657  mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0);
8658  mCachedMarginValid = false;
8659  }
8660 }
8661 
8670 {
8671  mAxisPainter->tickLabelSide = side;
8672  mCachedMarginValid = false;
8673 }
8674 
8710 void QCPAxis::setNumberFormat(const QString &formatCode)
8711 {
8712  if (formatCode.isEmpty())
8713  {
8714  qDebug() << Q_FUNC_INFO << "Passed formatCode is empty";
8715  return;
8716  }
8717  mCachedMarginValid = false;
8718 
8719  // interpret first char as number format char:
8720  QString allowedFormatChars(QLatin1String("eEfgG"));
8721  if (allowedFormatChars.contains(formatCode.at(0)))
8722  {
8723  mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1());
8724  } else
8725  {
8726  qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode;
8727  return;
8728  }
8729  if (formatCode.length() < 2)
8730  {
8731  mNumberBeautifulPowers = false;
8733  return;
8734  }
8735 
8736  // interpret second char as indicator for beautiful decimal powers:
8737  if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g')))
8738  {
8739  mNumberBeautifulPowers = true;
8740  } else
8741  {
8742  qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
8743  return;
8744  }
8745  if (formatCode.length() < 3)
8746  {
8748  return;
8749  }
8750 
8751  // interpret third char as indicator for dot or cross multiplication symbol:
8752  if (formatCode.at(2) == QLatin1Char('c'))
8753  {
8755  } else if (formatCode.at(2) == QLatin1Char('d'))
8756  {
8758  } else
8759  {
8760  qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
8761  return;
8762  }
8763 }
8764 
8770 void QCPAxis::setNumberPrecision(int precision)
8771 {
8772  if (mNumberPrecision != precision)
8773  {
8774  mNumberPrecision = precision;
8775  mCachedMarginValid = false;
8776  }
8777 }
8778 
8787 void QCPAxis::setTickLength(int inside, int outside)
8788 {
8789  setTickLengthIn(inside);
8790  setTickLengthOut(outside);
8791 }
8792 
8800 {
8801  if (mAxisPainter->tickLengthIn != inside)
8802  {
8803  mAxisPainter->tickLengthIn = inside;
8804  }
8805 }
8806 
8814 void QCPAxis::setTickLengthOut(int outside)
8815 {
8816  if (mAxisPainter->tickLengthOut != outside)
8817  {
8818  mAxisPainter->tickLengthOut = outside;
8819  mCachedMarginValid = false; // only outside tick length can change margin
8820  }
8821 }
8822 
8830 void QCPAxis::setSubTicks(bool show)
8831 {
8832  if (mSubTicks != show)
8833  {
8834  mSubTicks = show;
8835  mCachedMarginValid = false;
8836  }
8837 }
8838 
8847 void QCPAxis::setSubTickLength(int inside, int outside)
8848 {
8849  setSubTickLengthIn(inside);
8850  setSubTickLengthOut(outside);
8851 }
8852 
8860 {
8861  if (mAxisPainter->subTickLengthIn != inside)
8862  {
8863  mAxisPainter->subTickLengthIn = inside;
8864  }
8865 }
8866 
8875 {
8876  if (mAxisPainter->subTickLengthOut != outside)
8877  {
8878  mAxisPainter->subTickLengthOut = outside;
8879  mCachedMarginValid = false; // only outside tick length can change margin
8880  }
8881 }
8882 
8888 void QCPAxis::setBasePen(const QPen &pen)
8889 {
8890  mBasePen = pen;
8891 }
8892 
8898 void QCPAxis::setTickPen(const QPen &pen)
8899 {
8900  mTickPen = pen;
8901 }
8902 
8908 void QCPAxis::setSubTickPen(const QPen &pen)
8909 {
8910  mSubTickPen = pen;
8911 }
8912 
8918 void QCPAxis::setLabelFont(const QFont &font)
8919 {
8920  if (mLabelFont != font)
8921  {
8922  mLabelFont = font;
8923  mCachedMarginValid = false;
8924  }
8925 }
8926 
8932 void QCPAxis::setLabelColor(const QColor &color)
8933 {
8934  mLabelColor = color;
8935 }
8936 
8941 void QCPAxis::setLabel(const QString &str)
8942 {
8943  if (mLabel != str)
8944  {
8945  mLabel = str;
8946  mCachedMarginValid = false;
8947  }
8948 }
8949 
8955 void QCPAxis::setLabelPadding(int padding)
8956 {
8958  {
8960  mCachedMarginValid = false;
8961  }
8962 }
8963 
8974 void QCPAxis::setPadding(int padding)
8975 {
8976  if (mPadding != padding)
8977  {
8978  mPadding = padding;
8979  mCachedMarginValid = false;
8980  }
8981 }
8982 
8991 void QCPAxis::setOffset(int offset)
8992 {
8994 }
8995 
9001 void QCPAxis::setSelectedTickLabelFont(const QFont &font)
9002 {
9003  if (font != mSelectedTickLabelFont)
9004  {
9005  mSelectedTickLabelFont = font;
9006  // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
9007  }
9008 }
9009 
9015 void QCPAxis::setSelectedLabelFont(const QFont &font)
9016 {
9017  mSelectedLabelFont = font;
9018  // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
9019 }
9020 
9027 {
9029  {
9031  }
9032 }
9033 
9040 {
9042 }
9043 
9049 void QCPAxis::setSelectedBasePen(const QPen &pen)
9050 {
9051  mSelectedBasePen = pen;
9052 }
9053 
9059 void QCPAxis::setSelectedTickPen(const QPen &pen)
9060 {
9061  mSelectedTickPen = pen;
9062 }
9063 
9069 void QCPAxis::setSelectedSubTickPen(const QPen &pen)
9070 {
9071  mSelectedSubTickPen = pen;
9072 }
9073 
9085 {
9086  mAxisPainter->lowerEnding = ending;
9087 }
9088 
9100 {
9101  mAxisPainter->upperEnding = ending;
9102 }
9103 
9111 void QCPAxis::moveRange(double diff)
9112 {
9113  QCPRange oldRange = mRange;
9114  if (mScaleType == stLinear)
9115  {
9116  mRange.lower += diff;
9117  mRange.upper += diff;
9118  } else // mScaleType == stLogarithmic
9119  {
9120  mRange.lower *= diff;
9121  mRange.upper *= diff;
9122  }
9123  emit rangeChanged(mRange);
9124  emit rangeChanged(mRange, oldRange);
9125 }
9126 
9136 void QCPAxis::scaleRange(double factor)
9137 {
9138  scaleRange(factor, range().center());
9139 }
9140 
9150 void QCPAxis::scaleRange(double factor, double center)
9151 {
9152  QCPRange oldRange = mRange;
9153  if (mScaleType == stLinear)
9154  {
9155  QCPRange newRange;
9156  newRange.lower = (mRange.lower-center)*factor + center;
9157  newRange.upper = (mRange.upper-center)*factor + center;
9158  if (QCPRange::validRange(newRange))
9159  mRange = newRange.sanitizedForLinScale();
9160  } else // mScaleType == stLogarithmic
9161  {
9162  if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range
9163  {
9164  QCPRange newRange;
9165  newRange.lower = qPow(mRange.lower/center, factor)*center;
9166  newRange.upper = qPow(mRange.upper/center, factor)*center;
9167  if (QCPRange::validRange(newRange))
9168  mRange = newRange.sanitizedForLogScale();
9169  } else
9170  qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
9171  }
9172  emit rangeChanged(mRange);
9173  emit rangeChanged(mRange, oldRange);
9174 }
9175 
9189 void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio)
9190 {
9191  int otherPixelSize, ownPixelSize;
9192 
9193  if (otherAxis->orientation() == Qt::Horizontal)
9194  otherPixelSize = otherAxis->axisRect()->width();
9195  else
9196  otherPixelSize = otherAxis->axisRect()->height();
9197 
9198  if (orientation() == Qt::Horizontal)
9199  ownPixelSize = axisRect()->width();
9200  else
9201  ownPixelSize = axisRect()->height();
9202 
9203  double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/double(otherPixelSize);
9204  setRange(range().center(), newRangeSize, Qt::AlignCenter);
9205 }
9206 
9213 void QCPAxis::rescale(bool onlyVisiblePlottables)
9214 {
9215  QCPRange newRange;
9216  bool haveRange = false;
9217  foreach (QCPAbstractPlottable *plottable, plottables())
9218  {
9219  if (!plottable->realVisibility() && onlyVisiblePlottables)
9220  continue;
9221  QCPRange plottableRange;
9222  bool currentFoundRange;
9223  QCP::SignDomain signDomain = QCP::sdBoth;
9224  if (mScaleType == stLogarithmic)
9225  signDomain = (mRange.upper < 0 ? QCP::sdNegative : QCP::sdPositive);
9226  if (plottable->keyAxis() == this)
9227  plottableRange = plottable->getKeyRange(currentFoundRange, signDomain);
9228  else
9229  plottableRange = plottable->getValueRange(currentFoundRange, signDomain);
9230  if (currentFoundRange)
9231  {
9232  if (!haveRange)
9233  newRange = plottableRange;
9234  else
9235  newRange.expand(plottableRange);
9236  haveRange = true;
9237  }
9238  }
9239  if (haveRange)
9240  {
9241  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
9242  {
9243  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
9244  if (mScaleType == stLinear)
9245  {
9246  newRange.lower = center-mRange.size()/2.0;
9247  newRange.upper = center+mRange.size()/2.0;
9248  } else // mScaleType == stLogarithmic
9249  {
9250  newRange.lower = center/qSqrt(mRange.upper/mRange.lower);
9251  newRange.upper = center*qSqrt(mRange.upper/mRange.lower);
9252  }
9253  }
9254  setRange(newRange);
9255  }
9256 }
9257 
9261 double QCPAxis::pixelToCoord(double value) const
9262 {
9263  if (orientation() == Qt::Horizontal)
9264  {
9265  if (mScaleType == stLinear)
9266  {
9267  if (!mRangeReversed)
9268  return (value-mAxisRect->left())/double(mAxisRect->width())*mRange.size()+mRange.lower;
9269  else
9270  return -(value-mAxisRect->left())/double(mAxisRect->width())*mRange.size()+mRange.upper;
9271  } else // mScaleType == stLogarithmic
9272  {
9273  if (!mRangeReversed)
9274  return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/double(mAxisRect->width()))*mRange.lower;
9275  else
9276  return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/double(mAxisRect->width()))*mRange.upper;
9277  }
9278  } else // orientation() == Qt::Vertical
9279  {
9280  if (mScaleType == stLinear)
9281  {
9282  if (!mRangeReversed)
9283  return (mAxisRect->bottom()-value)/double(mAxisRect->height())*mRange.size()+mRange.lower;
9284  else
9285  return -(mAxisRect->bottom()-value)/double(mAxisRect->height())*mRange.size()+mRange.upper;
9286  } else // mScaleType == stLogarithmic
9287  {
9288  if (!mRangeReversed)
9289  return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/double(mAxisRect->height()))*mRange.lower;
9290  else
9291  return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/double(mAxisRect->height()))*mRange.upper;
9292  }
9293  }
9294 }
9295 
9299 double QCPAxis::coordToPixel(double value) const
9300 {
9301  if (orientation() == Qt::Horizontal)
9302  {
9303  if (mScaleType == stLinear)
9304  {
9305  if (!mRangeReversed)
9306  return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left();
9307  else
9308  return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left();
9309  } else // mScaleType == stLogarithmic
9310  {
9311  if (value >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just draw it outside visible range
9312  return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200;
9313  else if (value <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, just draw it outside visible range
9314  return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200;
9315  else
9316  {
9317  if (!mRangeReversed)
9318  return qLn(value/mRange.lower)/qLn(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
9319  else
9320  return qLn(mRange.upper/value)/qLn(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left();
9321  }
9322  }
9323  } else // orientation() == Qt::Vertical
9324  {
9325  if (mScaleType == stLinear)
9326  {
9327  if (!mRangeReversed)
9328  return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height();
9329  else
9330  return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height();
9331  } else // mScaleType == stLogarithmic
9332  {
9333  if (value >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just draw it outside visible range
9334  return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200;
9335  else if (value <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, just draw it outside visible range
9336  return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200;
9337  else
9338  {
9339  if (!mRangeReversed)
9340  return mAxisRect->bottom()-qLn(value/mRange.lower)/qLn(mRange.upper/mRange.lower)*mAxisRect->height();
9341  else
9342  return mAxisRect->bottom()-qLn(mRange.upper/value)/qLn(mRange.upper/mRange.lower)*mAxisRect->height();
9343  }
9344  }
9345  }
9346 }
9347 
9358 {
9359  if (!mVisible)
9360  return spNone;
9361 
9362  if (mAxisPainter->axisSelectionBox().contains(pos.toPoint()))
9363  return spAxis;
9364  else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint()))
9365  return spTickLabels;
9366  else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint()))
9367  return spAxisLabel;
9368  else
9369  return spNone;
9370 }
9371 
9372 /* inherits documentation from base class */
9373 double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
9374 {
9375  if (!mParentPlot) return -1;
9376  SelectablePart part = getPartAt(pos);
9377  if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone)
9378  return -1;
9379 
9380  if (details)
9381  details->setValue(part);
9382  return mParentPlot->selectionTolerance()*0.99;
9383 }
9384 
9392 QList<QCPAbstractPlottable*> QCPAxis::plottables() const
9393 {
9394  QList<QCPAbstractPlottable*> result;
9395  if (!mParentPlot) return result;
9396 
9397  foreach (QCPAbstractPlottable *plottable, mParentPlot->mPlottables)
9398  {
9399  if (plottable->keyAxis() == this || plottable->valueAxis() == this)
9400  result.append(plottable);
9401  }
9402  return result;
9403 }
9404 
9410 QList<QCPGraph*> QCPAxis::graphs() const
9411 {
9412  QList<QCPGraph*> result;
9413  if (!mParentPlot) return result;
9414 
9415  foreach (QCPGraph *graph, mParentPlot->mGraphs)
9416  {
9417  if (graph->keyAxis() == this || graph->valueAxis() == this)
9418  result.append(graph);
9419  }
9420  return result;
9421 }
9422 
9429 QList<QCPAbstractItem*> QCPAxis::items() const
9430 {
9431  QList<QCPAbstractItem*> result;
9432  if (!mParentPlot) return result;
9433 
9434  foreach (QCPAbstractItem *item, mParentPlot->mItems)
9435  {
9436  foreach (QCPItemPosition *position, item->positions())
9437  {
9438  if (position->keyAxis() == this || position->valueAxis() == this)
9439  {
9440  result.append(item);
9441  break;
9442  }
9443  }
9444  }
9445  return result;
9446 }
9447 
9453 {
9454  switch (side)
9455  {
9456  case QCP::msLeft: return atLeft;
9457  case QCP::msRight: return atRight;
9458  case QCP::msTop: return atTop;
9459  case QCP::msBottom: return atBottom;
9460  default: break;
9461  }
9462  qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << static_cast<int>(side);
9463  return atLeft;
9464 }
9465 
9470 {
9471  switch (type)
9472  {
9473  case atLeft: return atRight;
9474  case atRight: return atLeft;
9475  case atBottom: return atTop;
9476  case atTop: return atBottom;
9477  }
9478  qDebug() << Q_FUNC_INFO << "invalid axis type";
9479  return atLeft;
9480 }
9481 
9482 /* inherits documentation from base class */
9483 void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
9484 {
9485  Q_UNUSED(event)
9486  SelectablePart part = details.value<SelectablePart>();
9487  if (mSelectableParts.testFlag(part))
9488  {
9489  SelectableParts selBefore = mSelectedParts;
9490  setSelectedParts(additive ? mSelectedParts^part : part);
9491  if (selectionStateChanged)
9492  *selectionStateChanged = mSelectedParts != selBefore;
9493  }
9494 }
9495 
9496 /* inherits documentation from base class */
9497 void QCPAxis::deselectEvent(bool *selectionStateChanged)
9498 {
9499  SelectableParts selBefore = mSelectedParts;
9501  if (selectionStateChanged)
9502  *selectionStateChanged = mSelectedParts != selBefore;
9503 }
9504 
9520 void QCPAxis::mousePressEvent(QMouseEvent *event, const QVariant &details)
9521 {
9522  Q_UNUSED(details)
9523  if (!mParentPlot->interactions().testFlag(QCP::iRangeDrag) ||
9524  !mAxisRect->rangeDrag().testFlag(orientation()) ||
9525  !mAxisRect->rangeDragAxes(orientation()).contains(this))
9526  {
9527  event->ignore();
9528  return;
9529  }
9530 
9531  if (event->buttons() & Qt::LeftButton)
9532  {
9533  mDragging = true;
9534  // initialize antialiasing backup in case we start dragging:
9536  {
9539  }
9540  // Mouse range dragging interaction:
9541  if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
9543  }
9544 }
9545 
9558 void QCPAxis::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
9559 {
9560  if (mDragging)
9561  {
9562  const double startPixel = orientation() == Qt::Horizontal ? startPos.x() : startPos.y();
9563  const double currentPixel = orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y();
9565  {
9566  const double diff = pixelToCoord(startPixel) - pixelToCoord(currentPixel);
9568  } else if (mScaleType == QCPAxis::stLogarithmic)
9569  {
9570  const double diff = pixelToCoord(startPixel) / pixelToCoord(currentPixel);
9572  }
9573 
9577  }
9578 }
9579 
9592 void QCPAxis::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
9593 {
9594  Q_UNUSED(event)
9595  Q_UNUSED(startPos)
9596  mDragging = false;
9598  {
9601  }
9602 }
9603 
9619 void QCPAxis::wheelEvent(QWheelEvent *event)
9620 {
9621  // Mouse range zooming interaction:
9622  if (!mParentPlot->interactions().testFlag(QCP::iRangeZoom) ||
9623  !mAxisRect->rangeZoom().testFlag(orientation()) ||
9624  !mAxisRect->rangeZoomAxes(orientation()).contains(this))
9625  {
9626  event->ignore();
9627  return;
9628  }
9629 
9630 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
9631  const double delta = event->delta();
9632 #else
9633  const double delta = event->angleDelta().y();
9634 #endif
9635 
9636 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
9637  const QPointF pos = event->pos();
9638 #else
9639  const QPointF pos = event->position();
9640 #endif
9641 
9642  const double wheelSteps = delta/120.0; // a single step delta is +/-120 usually
9643  const double factor = qPow(mAxisRect->rangeZoomFactor(orientation()), wheelSteps);
9644  scaleRange(factor, pixelToCoord(orientation() == Qt::Horizontal ? pos.x() : pos.y()));
9645  mParentPlot->replot();
9646 }
9647 
9664 {
9666 }
9667 
9675 {
9676  QVector<double> subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
9677  QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
9678  QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
9679  tickPositions.reserve(mTickVector.size());
9680  tickLabels.reserve(mTickVector.size());
9681  subTickPositions.reserve(mSubTickVector.size());
9682 
9683  if (mTicks)
9684  {
9685  for (int i=0; i<mTickVector.size(); ++i)
9686  {
9687  tickPositions.append(coordToPixel(mTickVector.at(i)));
9688  if (mTickLabels)
9689  tickLabels.append(mTickVectorLabels.at(i));
9690  }
9691 
9692  if (mSubTicks)
9693  {
9694  const int subTickCount = mSubTickVector.size();
9695  for (int i=0; i<subTickCount; ++i)
9696  subTickPositions.append(coordToPixel(mSubTickVector.at(i)));
9697  }
9698  }
9699 
9700  // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to draw the axis.
9701  // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
9716  mAxisPainter->tickPositions = tickPositions;
9718  mAxisPainter->subTickPositions = subTickPositions;
9719  mAxisPainter->draw(painter);
9720 }
9721 
9731 {
9732  if (!mParentPlot) return;
9733  if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return;
9734 
9735  QVector<QString> oldLabels = mTickVectorLabels;
9737  mCachedMarginValid &= mTickVectorLabels == oldLabels; // if labels have changed, margin might have changed, too
9738 }
9739 
9746 {
9747  return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen;
9748 }
9749 
9756 {
9757  return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen;
9758 }
9759 
9766 {
9768 }
9769 
9776 {
9778 }
9779 
9786 {
9788 }
9789 
9796 {
9798 }
9799 
9806 {
9808 }
9809 
9825 {
9826  if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis
9827  return 0;
9828 
9829  if (mCachedMarginValid)
9830  return mCachedMargin;
9831 
9832  // run through similar steps as QCPAxis::draw, and calculate margin needed to fit axis and its labels
9833  int margin = 0;
9834 
9835  QVector<double> tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter
9836  QVector<QString> tickLabels; // the final vector passed to QCPAxisPainter
9837  tickPositions.reserve(mTickVector.size());
9838  tickLabels.reserve(mTickVector.size());
9839 
9840  if (mTicks)
9841  {
9842  for (int i=0; i<mTickVector.size(); ++i)
9843  {
9844  tickPositions.append(coordToPixel(mTickVector.at(i)));
9845  if (mTickLabels)
9846  tickLabels.append(mTickVectorLabels.at(i));
9847  }
9848  }
9849  // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size.
9850  // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters
9857  mAxisPainter->tickPositions = tickPositions;
9859  margin += mAxisPainter->size();
9860  margin += mPadding;
9861 
9862  mCachedMargin = margin;
9863  mCachedMarginValid = true;
9864  return margin;
9865 }
9866 
9867 /* inherits documentation from base class */
9869 {
9870  return QCP::iSelectAxes;
9871 }
9872 
9873 
9877 
9895  type(QCPAxis::atLeft),
9896  basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
9897  lowerEnding(QCPLineEnding::esNone),
9898  upperEnding(QCPLineEnding::esNone),
9899  labelPadding(0),
9900  tickLabelPadding(0),
9901  tickLabelRotation(0),
9902  tickLabelSide(QCPAxis::lsOutside),
9903  substituteExponent(true),
9904  numberMultiplyCross(false),
9905  tickLengthIn(5),
9906  tickLengthOut(0),
9907  subTickLengthIn(2),
9908  subTickLengthOut(0),
9909  tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
9910  subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
9911  offset(0),
9912  abbreviateDecimalPowers(false),
9913  reversedEndings(false),
9914  mParentPlot(parentPlot),
9915  mLabelCache(16) // cache at most 16 (tick) labels
9916 {
9917 }
9918 
9920 {
9921 }
9922 
9931 {
9932  QByteArray newHash = generateLabelParameterHash();
9933  if (newHash != mLabelParameterHash)
9934  {
9935  mLabelCache.clear();
9936  mLabelParameterHash = newHash;
9937  }
9938 
9939  QPoint origin;
9940  switch (type)
9941  {
9942  case QCPAxis::atLeft: origin = axisRect.bottomLeft() +QPoint(-offset, 0); break;
9943  case QCPAxis::atRight: origin = axisRect.bottomRight()+QPoint(+offset, 0); break;
9944  case QCPAxis::atTop: origin = axisRect.topLeft() +QPoint(0, -offset); break;
9945  case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break;
9946  }
9947 
9948  double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes)
9949  switch (type)
9950  {
9951  case QCPAxis::atTop: yCor = -1; break;
9952  case QCPAxis::atRight: xCor = 1; break;
9953  default: break;
9954  }
9955  int margin = 0;
9956  // draw baseline:
9957  QLineF baseLine;
9958  painter->setPen(basePen);
9959  if (QCPAxis::orientation(type) == Qt::Horizontal)
9960  baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor));
9961  else
9962  baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor));
9963  if (reversedEndings)
9964  baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later
9965  painter->drawLine(baseLine);
9966 
9967  // draw ticks:
9968  if (!tickPositions.isEmpty())
9969  {
9970  painter->setPen(tickPen);
9971  int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis)
9972  if (QCPAxis::orientation(type) == Qt::Horizontal)
9973  {
9974  foreach (double tickPos, tickPositions)
9975  painter->drawLine(QLineF(tickPos+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPos+xCor, origin.y()+tickLengthIn*tickDir+yCor));
9976  } else
9977  {
9978  foreach (double tickPos, tickPositions)
9979  painter->drawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPos+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPos+yCor));
9980  }
9981  }
9982 
9983  // draw subticks:
9984  if (!subTickPositions.isEmpty())
9985  {
9986  painter->setPen(subTickPen);
9987  // direction of ticks ("inward" is right for left axis and left for right axis)
9988  int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1;
9989  if (QCPAxis::orientation(type) == Qt::Horizontal)
9990  {
9991  foreach (double subTickPos, subTickPositions)
9992  painter->drawLine(QLineF(subTickPos+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPos+xCor, origin.y()+subTickLengthIn*tickDir+yCor));
9993  } else
9994  {
9995  foreach (double subTickPos, subTickPositions)
9996  painter->drawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPos+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPos+yCor));
9997  }
9998  }
9999  margin += qMax(0, qMax(tickLengthOut, subTickLengthOut));
10000 
10001  // draw axis base endings:
10002  bool antialiasingBackup = painter->antialiasing();
10003  painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't
10004  painter->setBrush(QBrush(basePen.color()));
10005  QCPVector2D baseLineVector(baseLine.dx(), baseLine.dy());
10007  lowerEnding.draw(painter, QCPVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector);
10009  upperEnding.draw(painter, QCPVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector);
10010  painter->setAntialiasing(antialiasingBackup);
10011 
10012  // tick labels:
10013  QRect oldClipRect;
10014  if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect
10015  {
10016  oldClipRect = painter->clipRegion().boundingRect();
10017  painter->setClipRect(axisRect);
10018  }
10019  QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label
10020  if (!tickLabels.isEmpty())
10021  {
10023  margin += tickLabelPadding;
10024  painter->setFont(tickLabelFont);
10025  painter->setPen(QPen(tickLabelColor));
10026  const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size());
10027  int distanceToAxis = margin;
10029  distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
10030  for (int i=0; i<maxLabelIndex; ++i)
10031  placeTickLabel(painter, tickPositions.at(i), distanceToAxis, tickLabels.at(i), &tickLabelsSize);
10033  margin += (QCPAxis::orientation(type) == Qt::Horizontal) ? tickLabelsSize.height() : tickLabelsSize.width();
10034  }
10036  painter->setClipRect(oldClipRect);
10037 
10038  // axis label:
10039  QRect labelBounds;
10040  if (!label.isEmpty())
10041  {
10042  margin += labelPadding;
10043  painter->setFont(labelFont);
10044  painter->setPen(QPen(labelColor));
10045  labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label);
10046  if (type == QCPAxis::atLeft)
10047  {
10048  QTransform oldTransform = painter->transform();
10049  painter->translate((origin.x()-margin-labelBounds.height()), origin.y());
10050  painter->rotate(-90);
10051  painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
10052  painter->setTransform(oldTransform);
10053  }
10054  else if (type == QCPAxis::atRight)
10055  {
10056  QTransform oldTransform = painter->transform();
10057  painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height());
10058  painter->rotate(90);
10059  painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
10060  painter->setTransform(oldTransform);
10061  }
10062  else if (type == QCPAxis::atTop)
10063  painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
10064  else if (type == QCPAxis::atBottom)
10065  painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label);
10066  }
10067 
10068  // set selection boxes:
10069  int selectionTolerance = 0;
10070  if (mParentPlot)
10071  selectionTolerance = mParentPlot->selectionTolerance();
10072  else
10073  qDebug() << Q_FUNC_INFO << "mParentPlot is null";
10074  int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance);
10075  int selAxisInSize = selectionTolerance;
10076  int selTickLabelSize;
10077  int selTickLabelOffset;
10079  {
10080  selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
10081  selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding;
10082  } else
10083  {
10084  selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
10085  selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding);
10086  }
10087  int selLabelSize = labelBounds.height();
10088  int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding;
10089  if (type == QCPAxis::atLeft)
10090  {
10091  mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom());
10092  mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom());
10093  mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom());
10094  } else if (type == QCPAxis::atRight)
10095  {
10096  mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom());
10097  mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom());
10098  mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom());
10099  } else if (type == QCPAxis::atTop)
10100  {
10101  mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize);
10102  mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset);
10103  mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset);
10104  } else if (type == QCPAxis::atBottom)
10105  {
10106  mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize);
10107  mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset);
10108  mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset);
10109  }
10110  mAxisSelectionBox = mAxisSelectionBox.normalized();
10112  mLabelSelectionBox = mLabelSelectionBox.normalized();
10113  // draw hitboxes for debug purposes:
10114  //painter->setBrush(Qt::NoBrush);
10115  //painter->drawRects(QVector<QRect>() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox);
10116 }
10117 
10124 {
10125  int result = 0;
10126 
10127  QByteArray newHash = generateLabelParameterHash();
10128  if (newHash != mLabelParameterHash)
10129  {
10130  mLabelCache.clear();
10131  mLabelParameterHash = newHash;
10132  }
10133 
10134  // get length of tick marks pointing outwards:
10135  if (!tickPositions.isEmpty())
10136  result += qMax(0, qMax(tickLengthOut, subTickLengthOut));
10137 
10138  // calculate size of tick labels:
10140  {
10141  QSize tickLabelsSize(0, 0);
10142  if (!tickLabels.isEmpty())
10143  {
10144  foreach (const QString &tickLabel, tickLabels)
10145  getMaxTickLabelSize(tickLabelFont, tickLabel, &tickLabelsSize);
10146  result += QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width();
10147  result += tickLabelPadding;
10148  }
10149  }
10150 
10151  // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees):
10152  if (!label.isEmpty())
10153  {
10154  QFontMetrics fontMetrics(labelFont);
10155  QRect bounds;
10156  bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label);
10157  result += bounds.height() + labelPadding;
10158  }
10159 
10160  return result;
10161 }
10162 
10170 {
10171  mLabelCache.clear();
10172 }
10173 
10182 {
10183  QByteArray result;
10184  result.append(QByteArray::number(mParentPlot->bufferDevicePixelRatio()));
10185  result.append(QByteArray::number(tickLabelRotation));
10186  result.append(QByteArray::number(int(tickLabelSide)));
10187  result.append(QByteArray::number(int(substituteExponent)));
10188  result.append(QByteArray::number(int(numberMultiplyCross)));
10189  result.append(tickLabelColor.name().toLatin1()+QByteArray::number(tickLabelColor.alpha(), 16));
10190  result.append(tickLabelFont.toString().toLatin1());
10191  return result;
10192 }
10193 
10213 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize)
10214 {
10215  // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly!
10216  if (text.isEmpty()) return;
10217  QSize finalSize;
10218  QPointF labelAnchor;
10219  switch (type)
10220  {
10221  case QCPAxis::atLeft: labelAnchor = QPointF(axisRect.left()-distanceToAxis-offset, position); break;
10222  case QCPAxis::atRight: labelAnchor = QPointF(axisRect.right()+distanceToAxis+offset, position); break;
10223  case QCPAxis::atTop: labelAnchor = QPointF(position, axisRect.top()-distanceToAxis-offset); break;
10224  case QCPAxis::atBottom: labelAnchor = QPointF(position, axisRect.bottom()+distanceToAxis+offset); break;
10225  }
10226  if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled
10227  {
10228  CachedLabel *cachedLabel = mLabelCache.take(text); // attempt to get label from cache
10229  if (!cachedLabel) // no cached label existed, create it
10230  {
10231  cachedLabel = new CachedLabel;
10232  TickLabelData labelData = getTickLabelData(painter->font(), text);
10233  cachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft();
10234  if (!qFuzzyCompare(1.0, mParentPlot->bufferDevicePixelRatio()))
10235  {
10236  cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()*mParentPlot->bufferDevicePixelRatio());
10237 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
10238 # ifdef QCP_DEVICEPIXELRATIO_FLOAT
10239  cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatioF());
10240 # else
10241  cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio());
10242 # endif
10243 #endif
10244  } else
10245  cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size());
10246  cachedLabel->pixmap.fill(Qt::transparent);
10247  QCPPainter cachePainter(&cachedLabel->pixmap);
10248  cachePainter.setPen(painter->pen());
10249  drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData);
10250  }
10251  // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
10252  bool labelClippedByBorder = false;
10254  {
10255  if (QCPAxis::orientation(type) == Qt::Horizontal)
10256  labelClippedByBorder = labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width()/mParentPlot->bufferDevicePixelRatio() > viewportRect.right() || labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left();
10257  else
10258  labelClippedByBorder = labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height()/mParentPlot->bufferDevicePixelRatio() > viewportRect.bottom() || labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top();
10259  }
10260  if (!labelClippedByBorder)
10261  {
10262  painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap);
10263  finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio();
10264  }
10265  mLabelCache.insert(text, cachedLabel); // return label to cache or insert for the first time if newly created
10266  } else // label caching disabled, draw text directly on surface:
10267  {
10268  TickLabelData labelData = getTickLabelData(painter->font(), text);
10269  QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData);
10270  // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels):
10271  bool labelClippedByBorder = false;
10273  {
10274  if (QCPAxis::orientation(type) == Qt::Horizontal)
10275  labelClippedByBorder = finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left();
10276  else
10277  labelClippedByBorder = finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top();
10278  }
10279  if (!labelClippedByBorder)
10280  {
10281  drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData);
10282  finalSize = labelData.rotatedTotalBounds.size();
10283  }
10284  }
10285 
10286  // expand passed tickLabelsSize if current tick label is larger:
10287  if (finalSize.width() > tickLabelsSize->width())
10288  tickLabelsSize->setWidth(finalSize.width());
10289  if (finalSize.height() > tickLabelsSize->height())
10290  tickLabelsSize->setHeight(finalSize.height());
10291 }
10292 
10302 void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const
10303 {
10304  // backup painter settings that we're about to change:
10305  QTransform oldTransform = painter->transform();
10306  QFont oldFont = painter->font();
10307 
10308  // transform painter to position/rotation:
10309  painter->translate(x, y);
10310  if (!qFuzzyIsNull(tickLabelRotation))
10311  painter->rotate(tickLabelRotation);
10312 
10313  // draw text:
10314  if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used
10315  {
10316  painter->setFont(labelData.baseFont);
10317  painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart);
10318  if (!labelData.suffixPart.isEmpty())
10319  painter->drawText(labelData.baseBounds.width()+1+labelData.expBounds.width(), 0, 0, 0, Qt::TextDontClip, labelData.suffixPart);
10320  painter->setFont(labelData.expFont);
10321  painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart);
10322  } else
10323  {
10324  painter->setFont(labelData.baseFont);
10325  painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart);
10326  }
10327 
10328  // reset painter settings to what it was before:
10329  painter->setTransform(oldTransform);
10330  painter->setFont(oldFont);
10331 }
10332 
10342 {
10343  TickLabelData result;
10344 
10345  // determine whether beautiful decimal powers should be used
10346  bool useBeautifulPowers = false;
10347  int ePos = -1; // first index of exponent part, text before that will be basePart, text until eLast will be expPart
10348  int eLast = -1; // last index of exponent part, rest of text after this will be suffixPart
10349  if (substituteExponent)
10350  {
10351  ePos = text.indexOf(QLatin1Char('e'));
10352  if (ePos > 0 && text.at(ePos-1).isDigit())
10353  {
10354  eLast = ePos;
10355  while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char('+') || text.at(eLast+1) == QLatin1Char('-') || text.at(eLast+1).isDigit()))
10356  ++eLast;
10357  if (eLast > ePos) // only if also to right of 'e' is a digit/+/- interpret it as beautifiable power
10358  useBeautifulPowers = true;
10359  }
10360  }
10361 
10362  // calculate text bounding rects and do string preparation for beautiful decimal powers:
10363  result.baseFont = font;
10364  if (result.baseFont.pointSizeF() > 0) // might return -1 if specified with setPixelSize, in that case we can't do correction in next line
10365  result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding
10366  if (useBeautifulPowers)
10367  {
10368  // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent:
10369  result.basePart = text.left(ePos);
10370  result.suffixPart = text.mid(eLast+1); // also drawn normally but after exponent
10371  // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base:
10372  if (abbreviateDecimalPowers && result.basePart == QLatin1String("1"))
10373  result.basePart = QLatin1String("10");
10374  else
10375  result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10");
10376  result.expPart = text.mid(ePos+1, eLast-ePos);
10377  // clip "+" and leading zeros off expPart:
10378  while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e'
10379  result.expPart.remove(1, 1);
10380  if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+'))
10381  result.expPart.remove(0, 1);
10382  // prepare smaller font for exponent:
10383  result.expFont = font;
10384  if (result.expFont.pointSize() > 0)
10385  result.expFont.setPointSize(int(result.expFont.pointSize()*0.75));
10386  else
10387  result.expFont.setPixelSize(int(result.expFont.pixelSize()*0.75));
10388  // calculate bounding rects of base part(s), exponent part and total one:
10389  result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart);
10390  result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart);
10391  if (!result.suffixPart.isEmpty())
10392  result.suffixBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.suffixPart);
10393  result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+result.suffixBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA
10394  } else // useBeautifulPowers == false
10395  {
10396  result.basePart = text;
10397  result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart);
10398  }
10399  result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler
10400 
10401  // calculate possibly different bounding rect after rotation:
10402  result.rotatedTotalBounds = result.totalBounds;
10403  if (!qFuzzyIsNull(tickLabelRotation))
10404  {
10405  QTransform transform;
10406  transform.rotate(tickLabelRotation);
10407  result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds);
10408  }
10409 
10410  return result;
10411 }
10412 
10424 {
10425  /*
10426  calculate label offset from base point at tick (non-trivial, for best visual appearance): short
10427  explanation for bottom axis: The anchor, i.e. the point in the label that is placed
10428  horizontally under the corresponding tick is always on the label side that is closer to the
10429  axis (e.g. the left side of the text when we're rotating clockwise). On that side, the height
10430  is halved and the resulting point is defined the anchor. This way, a 90 degree rotated text
10431  will be centered under the tick (i.e. displaced horizontally by half its height). At the same
10432  time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick
10433  labels.
10434  */
10435  bool doRotation = !qFuzzyIsNull(tickLabelRotation);
10436  bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes.
10437  double radians = tickLabelRotation/180.0*M_PI;
10438  double x = 0;
10439  double y = 0;
10440  if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label
10441  {
10442  if (doRotation)
10443  {
10444  if (tickLabelRotation > 0)
10445  {
10446  x = -qCos(radians)*labelData.totalBounds.width();
10447  y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0;
10448  } else
10449  {
10450  x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height();
10451  y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0;
10452  }
10453  } else
10454  {
10455  x = -labelData.totalBounds.width();
10456  y = -labelData.totalBounds.height()/2.0;
10457  }
10458  } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label
10459  {
10460  if (doRotation)
10461  {
10462  if (tickLabelRotation > 0)
10463  {
10464  x = +qSin(radians)*labelData.totalBounds.height();
10465  y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0;
10466  } else
10467  {
10468  x = 0;
10469  y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0;
10470  }
10471  } else
10472  {
10473  x = 0;
10474  y = -labelData.totalBounds.height()/2.0;
10475  }
10476  } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label
10477  {
10478  if (doRotation)
10479  {
10480  if (tickLabelRotation > 0)
10481  {
10482  x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0;
10483  y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height();
10484  } else
10485  {
10486  x = -qSin(-radians)*labelData.totalBounds.height()/2.0;
10487  y = -qCos(-radians)*labelData.totalBounds.height();
10488  }
10489  } else
10490  {
10491  x = -labelData.totalBounds.width()/2.0;
10492  y = -labelData.totalBounds.height();
10493  }
10494  } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label
10495  {
10496  if (doRotation)
10497  {
10498  if (tickLabelRotation > 0)
10499  {
10500  x = +qSin(radians)*labelData.totalBounds.height()/2.0;
10501  y = 0;
10502  } else
10503  {
10504  x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0;
10505  y = +qSin(-radians)*labelData.totalBounds.width();
10506  }
10507  } else
10508  {
10509  x = -labelData.totalBounds.width()/2.0;
10510  y = 0;
10511  }
10512  }
10513 
10514  return {x, y};
10515 }
10516 
10524 void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const
10525 {
10526  // note: this function must return the same tick label sizes as the placeTickLabel function.
10527  QSize finalSize;
10528  if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label
10529  {
10530  const CachedLabel *cachedLabel = mLabelCache.object(text);
10531  finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio();
10532  } else // label caching disabled or no label with this text cached:
10533  {
10534  TickLabelData labelData = getTickLabelData(font, text);
10535  finalSize = labelData.rotatedTotalBounds.size();
10536  }
10537 
10538  // expand passed tickLabelsSize if current tick label is larger:
10539  if (finalSize.width() > tickLabelsSize->width())
10540  tickLabelsSize->setWidth(finalSize.width());
10541  if (finalSize.height() > tickLabelsSize->height())
10542  tickLabelsSize->setHeight(finalSize.height());
10543 }
10544 /* end of 'src/axis/axis.cpp' */
10545 
10546 
10547 /* including file 'src/scatterstyle.cpp' */
10548 /* modified 2021-03-29T02:30:44, size 17466 */
10549 
10553 
10604 /* start documentation of inline functions */
10605 
10627 /* end documentation of inline functions */
10628 
10636  mSize(6),
10637  mShape(ssNone),
10638  mPen(Qt::NoPen),
10639  mBrush(Qt::NoBrush),
10640  mPenDefined(false)
10641 {
10642 }
10643 
10652  mSize(size),
10653  mShape(shape),
10654  mPen(Qt::NoPen),
10655  mBrush(Qt::NoBrush),
10656  mPenDefined(false)
10657 {
10658 }
10659 
10664 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) :
10665  mSize(size),
10666  mShape(shape),
10667  mPen(QPen(color)),
10668  mBrush(Qt::NoBrush),
10669  mPenDefined(true)
10670 {
10671 }
10672 
10677 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) :
10678  mSize(size),
10679  mShape(shape),
10680  mPen(QPen(color)),
10681  mBrush(QBrush(fill)),
10682  mPenDefined(true)
10683 {
10684 }
10685 
10701 QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) :
10702  mSize(size),
10703  mShape(shape),
10704  mPen(pen),
10705  mBrush(brush),
10706  mPenDefined(pen.style() != Qt::NoPen)
10707 {
10708 }
10709 
10714 QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) :
10715  mSize(5),
10716  mShape(ssPixmap),
10717  mPen(Qt::NoPen),
10718  mBrush(Qt::NoBrush),
10719  mPixmap(pixmap),
10720  mPenDefined(false)
10721 {
10722 }
10723 
10733 QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) :
10734  mSize(size),
10735  mShape(ssCustom),
10736  mPen(pen),
10737  mBrush(brush),
10738  mCustomPath(customPath),
10739  mPenDefined(pen.style() != Qt::NoPen)
10740 {
10741 }
10742 
10746 void QCPScatterStyle::setFromOther(const QCPScatterStyle &other, ScatterProperties properties)
10747 {
10748  if (properties.testFlag(spPen))
10749  {
10750  setPen(other.pen());
10751  if (!other.isPenDefined())
10752  undefinePen();
10753  }
10754  if (properties.testFlag(spBrush))
10755  setBrush(other.brush());
10756  if (properties.testFlag(spSize))
10757  setSize(other.size());
10758  if (properties.testFlag(spShape))
10759  {
10760  setShape(other.shape());
10761  if (other.shape() == ssPixmap)
10762  setPixmap(other.pixmap());
10763  else if (other.shape() == ssCustom)
10764  setCustomPath(other.customPath());
10765  }
10766 }
10767 
10773 void QCPScatterStyle::setSize(double size)
10774 {
10775  mSize = size;
10776 }
10777 
10787 {
10788  mShape = shape;
10789 }
10790 
10800 void QCPScatterStyle::setPen(const QPen &pen)
10801 {
10802  mPenDefined = true;
10803  mPen = pen;
10804 }
10805 
10812 void QCPScatterStyle::setBrush(const QBrush &brush)
10813 {
10814  mBrush = brush;
10815 }
10816 
10824 void QCPScatterStyle::setPixmap(const QPixmap &pixmap)
10825 {
10826  setShape(ssPixmap);
10827  mPixmap = pixmap;
10828 }
10829 
10835 void QCPScatterStyle::setCustomPath(const QPainterPath &customPath)
10836 {
10837  setShape(ssCustom);
10839 }
10840 
10848 {
10849  mPenDefined = false;
10850 }
10851 
10861 void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const
10862 {
10863  painter->setPen(mPenDefined ? mPen : defaultPen);
10864  painter->setBrush(mBrush);
10865 }
10866 
10875 void QCPScatterStyle::drawShape(QCPPainter *painter, const QPointF &pos) const
10876 {
10877  drawShape(painter, pos.x(), pos.y());
10878 }
10879 
10883 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const
10884 {
10885  double w = mSize/2.0;
10886  switch (mShape)
10887  {
10888  case ssNone: break;
10889  case ssDot:
10890  {
10891  painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y));
10892  break;
10893  }
10894  case ssCross:
10895  {
10896  painter->drawLine(QLineF(x-w, y-w, x+w, y+w));
10897  painter->drawLine(QLineF(x-w, y+w, x+w, y-w));
10898  break;
10899  }
10900  case ssPlus:
10901  {
10902  painter->drawLine(QLineF(x-w, y, x+w, y));
10903  painter->drawLine(QLineF( x, y+w, x, y-w));
10904  break;
10905  }
10906  case ssCircle:
10907  {
10908  painter->drawEllipse(QPointF(x , y), w, w);
10909  break;
10910  }
10911  case ssDisc:
10912  {
10913  QBrush b = painter->brush();
10914  painter->setBrush(painter->pen().color());
10915  painter->drawEllipse(QPointF(x , y), w, w);
10916  painter->setBrush(b);
10917  break;
10918  }
10919  case ssSquare:
10920  {
10921  painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
10922  break;
10923  }
10924  case ssDiamond:
10925  {
10926  QPointF lineArray[4] = {QPointF(x-w, y),
10927  QPointF( x, y-w),
10928  QPointF(x+w, y),
10929  QPointF( x, y+w)};
10930  painter->drawPolygon(lineArray, 4);
10931  break;
10932  }
10933  case ssStar:
10934  {
10935  painter->drawLine(QLineF(x-w, y, x+w, y));
10936  painter->drawLine(QLineF( x, y+w, x, y-w));
10937  painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707));
10938  painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707));
10939  break;
10940  }
10941  case ssTriangle:
10942  {
10943  QPointF lineArray[3] = {QPointF(x-w, y+0.755*w),
10944  QPointF(x+w, y+0.755*w),
10945  QPointF( x, y-0.977*w)};
10946  painter->drawPolygon(lineArray, 3);
10947  break;
10948  }
10949  case ssTriangleInverted:
10950  {
10951  QPointF lineArray[3] = {QPointF(x-w, y-0.755*w),
10952  QPointF(x+w, y-0.755*w),
10953  QPointF( x, y+0.977*w)};
10954  painter->drawPolygon(lineArray, 3);
10955  break;
10956  }
10957  case ssCrossSquare:
10958  {
10959  painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
10960  painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95));
10961  painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w));
10962  break;
10963  }
10964  case ssPlusSquare:
10965  {
10966  painter->drawRect(QRectF(x-w, y-w, mSize, mSize));
10967  painter->drawLine(QLineF(x-w, y, x+w*0.95, y));
10968  painter->drawLine(QLineF( x, y+w, x, y-w));
10969  break;
10970  }
10971  case ssCrossCircle:
10972  {
10973  painter->drawEllipse(QPointF(x, y), w, w);
10974  painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670));
10975  painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707));
10976  break;
10977  }
10978  case ssPlusCircle:
10979  {
10980  painter->drawEllipse(QPointF(x, y), w, w);
10981  painter->drawLine(QLineF(x-w, y, x+w, y));
10982  painter->drawLine(QLineF( x, y+w, x, y-w));
10983  break;
10984  }
10985  case ssPeace:
10986  {
10987  painter->drawEllipse(QPointF(x, y), w, w);
10988  painter->drawLine(QLineF(x, y-w, x, y+w));
10989  painter->drawLine(QLineF(x, y, x-w*0.707, y+w*0.707));
10990  painter->drawLine(QLineF(x, y, x+w*0.707, y+w*0.707));
10991  break;
10992  }
10993  case ssPixmap:
10994  {
10995  const double widthHalf = mPixmap.width()*0.5;
10996  const double heightHalf = mPixmap.height()*0.5;
10997 #if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
10998  const QRectF clipRect = painter->clipRegion().boundingRect().adjusted(-widthHalf, -heightHalf, widthHalf, heightHalf);
10999 #else
11000  const QRectF clipRect = painter->clipBoundingRect().adjusted(-widthHalf, -heightHalf, widthHalf, heightHalf);
11001 #endif
11002  if (clipRect.contains(x, y))
11003  painter->drawPixmap(qRound(x-widthHalf), qRound(y-heightHalf), mPixmap);
11004  break;
11005  }
11006  case ssCustom:
11007  {
11008  QTransform oldTransform = painter->transform();
11009  painter->translate(x, y);
11010  painter->scale(mSize/6.0, mSize/6.0);
11011  painter->drawPath(mCustomPath);
11012  painter->setTransform(oldTransform);
11013  break;
11014  }
11015  }
11016 }
11017 /* end of 'src/scatterstyle.cpp' */
11018 
11019 
11020 /* including file 'src/plottable.cpp' */
11021 /* modified 2021-03-29T02:30:44, size 38818 */
11022 
11026 
11057  mPen(QColor(80, 80, 255), 2.5),
11058  mBrush(Qt::NoBrush),
11059  mUsedScatterProperties(QCPScatterStyle::spNone),
11060  mPlottable(nullptr)
11061 {
11062 }
11063 
11065 {
11066 }
11067 
11071 void QCPSelectionDecorator::setPen(const QPen &pen)
11072 {
11073  mPen = pen;
11074 }
11075 
11079 void QCPSelectionDecorator::setBrush(const QBrush &brush)
11080 {
11081  mBrush = brush;
11082 }
11083 
11091 void QCPSelectionDecorator::setScatterStyle(const QCPScatterStyle &scatterStyle, QCPScatterStyle::ScatterProperties usedProperties)
11092 {
11094  setUsedScatterProperties(usedProperties);
11095 }
11096 
11104 void QCPSelectionDecorator::setUsedScatterProperties(const QCPScatterStyle::ScatterProperties &properties)
11105 {
11106  mUsedScatterProperties = properties;
11107 }
11108 
11115 {
11116  painter->setPen(mPen);
11117 }
11118 
11125 {
11126  painter->setBrush(mBrush);
11127 }
11128 
11138 {
11139  QCPScatterStyle result(unselectedStyle);
11141 
11142  // if style shall inherit pen from plottable (has no own pen defined), give it the selected
11143  // plottable pen explicitly, so it doesn't use the unselected plottable pen when used in the
11144  // plottable:
11145  if (!result.isPenDefined())
11146  result.setPen(mPen);
11147 
11148  return result;
11149 }
11150 
11156 {
11157  setPen(other->pen());
11158  setBrush(other->brush());
11160 }
11161 
11171 {
11172  Q_UNUSED(painter)
11173  Q_UNUSED(selection)
11174 }
11175 
11186 {
11187  if (!mPlottable)
11188  {
11189  mPlottable = plottable;
11190  return true;
11191  } else
11192  {
11193  qDebug() << Q_FUNC_INFO << "This selection decorator is already registered with plottable:" << reinterpret_cast<quintptr>(mPlottable);
11194  return false;
11195  }
11196 }
11197 
11198 
11202 
11284 /* start of documentation of inline functions */
11285 
11320 /* end of documentation of inline functions */
11321 /* start of documentation of pure virtual functions */
11322 
11373 /* end of documentation of pure virtual functions */
11374 /* start of documentation of signals */
11375 
11401 /* end of documentation of signals */
11402 
11415  QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()),
11416  mName(),
11417  mAntialiasedFill(true),
11418  mAntialiasedScatters(true),
11419  mPen(Qt::black),
11420  mBrush(Qt::NoBrush),
11421  mKeyAxis(keyAxis),
11422  mValueAxis(valueAxis),
11423  mSelectable(QCP::stWhole),
11424  mSelectionDecorator(nullptr)
11425 {
11426  if (keyAxis->parentPlot() != valueAxis->parentPlot())
11427  qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis.";
11429  qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other.";
11430 
11433 }
11434 
11436 {
11437  if (mSelectionDecorator)
11438  {
11439  delete mSelectionDecorator;
11440  mSelectionDecorator = nullptr;
11441  }
11442 }
11443 
11448 void QCPAbstractPlottable::setName(const QString &name)
11449 {
11450  mName = name;
11451 }
11452 
11460 {
11461  mAntialiasedFill = enabled;
11462 }
11463 
11471 {
11472  mAntialiasedScatters = enabled;
11473 }
11474 
11483 void QCPAbstractPlottable::setPen(const QPen &pen)
11484 {
11485  mPen = pen;
11486 }
11487 
11497 void QCPAbstractPlottable::setBrush(const QBrush &brush)
11498 {
11499  mBrush = brush;
11500 }
11501 
11514 {
11515  mKeyAxis = axis;
11516 }
11517 
11530 {
11531  mValueAxis = axis;
11532 }
11533 
11534 
11554 {
11556  if (mSelection != selection)
11557  {
11559  emit selectionChanged(selected());
11561  }
11562 }
11563 
11574 {
11575  if (decorator)
11576  {
11577  if (decorator->registerWithPlottable(this))
11578  {
11579  delete mSelectionDecorator; // delete old decorator if necessary
11580  mSelectionDecorator = decorator;
11581  }
11582  } else if (mSelectionDecorator) // just clear decorator
11583  {
11584  delete mSelectionDecorator;
11585  mSelectionDecorator = nullptr;
11586  }
11587 }
11588 
11600 {
11601  if (mSelectable != selectable)
11602  {
11604  QCPDataSelection oldSelection = mSelection;
11607  if (mSelection != oldSelection)
11608  {
11609  emit selectionChanged(selected());
11611  }
11612  }
11613 }
11614 
11615 
11625 void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const
11626 {
11627  QCPAxis *keyAxis = mKeyAxis.data();
11628  QCPAxis *valueAxis = mValueAxis.data();
11629  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
11630 
11631  if (keyAxis->orientation() == Qt::Horizontal)
11632  {
11633  x = keyAxis->coordToPixel(key);
11634  y = valueAxis->coordToPixel(value);
11635  } else
11636  {
11637  y = keyAxis->coordToPixel(key);
11638  x = valueAxis->coordToPixel(value);
11639  }
11640 }
11641 
11646 const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const
11647 {
11648  QCPAxis *keyAxis = mKeyAxis.data();
11649  QCPAxis *valueAxis = mValueAxis.data();
11650  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); }
11651 
11652  if (keyAxis->orientation() == Qt::Horizontal)
11653  return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value));
11654  else
11655  return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key));
11656 }
11657 
11667 void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const
11668 {
11669  QCPAxis *keyAxis = mKeyAxis.data();
11670  QCPAxis *valueAxis = mValueAxis.data();
11671  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
11672 
11673  if (keyAxis->orientation() == Qt::Horizontal)
11674  {
11675  key = keyAxis->pixelToCoord(x);
11676  value = valueAxis->pixelToCoord(y);
11677  } else
11678  {
11679  key = keyAxis->pixelToCoord(y);
11680  value = valueAxis->pixelToCoord(x);
11681  }
11682 }
11683 
11688 void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const
11689 {
11690  pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value);
11691 }
11692 
11706 void QCPAbstractPlottable::rescaleAxes(bool onlyEnlarge) const
11707 {
11708  rescaleKeyAxis(onlyEnlarge);
11709  rescaleValueAxis(onlyEnlarge);
11710 }
11711 
11717 void QCPAbstractPlottable::rescaleKeyAxis(bool onlyEnlarge) const
11718 {
11719  QCPAxis *keyAxis = mKeyAxis.data();
11720  if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
11721 
11722  QCP::SignDomain signDomain = QCP::sdBoth;
11724  signDomain = (keyAxis->range().upper < 0 ? QCP::sdNegative : QCP::sdPositive);
11725 
11726  bool foundRange;
11727  QCPRange newRange = getKeyRange(foundRange, signDomain);
11728  if (foundRange)
11729  {
11730  if (onlyEnlarge)
11731  newRange.expand(keyAxis->range());
11732  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
11733  {
11734  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
11736  {
11737  newRange.lower = center-keyAxis->range().size()/2.0;
11738  newRange.upper = center+keyAxis->range().size()/2.0;
11739  } else // scaleType() == stLogarithmic
11740  {
11741  newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower);
11742  newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower);
11743  }
11744  }
11745  keyAxis->setRange(newRange);
11746  }
11747 }
11748 
11759 void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge, bool inKeyRange) const
11760 {
11761  QCPAxis *keyAxis = mKeyAxis.data();
11762  QCPAxis *valueAxis = mValueAxis.data();
11763  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
11764 
11765  QCP::SignDomain signDomain = QCP::sdBoth;
11767  signDomain = (valueAxis->range().upper < 0 ? QCP::sdNegative : QCP::sdPositive);
11768 
11769  bool foundRange;
11770  QCPRange newRange = getValueRange(foundRange, signDomain, inKeyRange ? keyAxis->range() : QCPRange());
11771  if (foundRange)
11772  {
11773  if (onlyEnlarge)
11774  newRange.expand(valueAxis->range());
11775  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
11776  {
11777  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
11779  {
11780  newRange.lower = center-valueAxis->range().size()/2.0;
11781  newRange.upper = center+valueAxis->range().size()/2.0;
11782  } else // scaleType() == stLogarithmic
11783  {
11784  newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower);
11785  newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower);
11786  }
11787  }
11788  valueAxis->setRange(newRange);
11789  }
11790 }
11791 
11807 {
11808  if (!legend)
11809  {
11810  qDebug() << Q_FUNC_INFO << "passed legend is null";
11811  return false;
11812  }
11813  if (legend->parentPlot() != mParentPlot)
11814  {
11815  qDebug() << Q_FUNC_INFO << "passed legend isn't in the same QCustomPlot as this plottable";
11816  return false;
11817  }
11818 
11819  if (!legend->hasItemWithPlottable(this))
11820  {
11821  legend->addItem(new QCPPlottableLegendItem(legend, this));
11822  return true;
11823  } else
11824  return false;
11825 }
11826 
11834 {
11835  if (!mParentPlot || !mParentPlot->legend)
11836  return false;
11837  else
11838  return addToLegend(mParentPlot->legend);
11839 }
11840 
11852 {
11853  if (!legend)
11854  {
11855  qDebug() << Q_FUNC_INFO << "passed legend is null";
11856  return false;
11857  }
11858 
11859  if (QCPPlottableLegendItem *lip = legend->itemWithPlottable(this))
11860  return legend->removeItem(lip);
11861  else
11862  return false;
11863 }
11864 
11872 {
11873  if (!mParentPlot || !mParentPlot->legend)
11874  return false;
11875  else
11877 }
11878 
11879 /* inherits documentation from base class */
11881 {
11882  if (mKeyAxis && mValueAxis)
11883  return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect();
11884  else
11885  return {};
11886 }
11887 
11888 /* inherits documentation from base class */
11890 {
11891  return QCP::iSelectPlottables;
11892 }
11893 
11910 {
11912 }
11913 
11926 {
11928 }
11929 
11942 {
11944 }
11945 
11946 /* inherits documentation from base class */
11947 void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
11948 {
11949  Q_UNUSED(event)
11950 
11951  if (mSelectable != QCP::stNone)
11952  {
11953  QCPDataSelection newSelection = details.value<QCPDataSelection>();
11954  QCPDataSelection selectionBefore = mSelection;
11955  if (additive)
11956  {
11957  if (mSelectable == QCP::stWhole) // in whole selection mode, we toggle to no selection even if currently unselected point was hit
11958  {
11959  if (selected())
11961  else
11962  setSelection(newSelection);
11963  } else // in all other selection modes we toggle selections of homogeneously selected/unselected segments
11964  {
11965  if (mSelection.contains(newSelection)) // if entire newSelection is already selected, toggle selection
11966  setSelection(mSelection-newSelection);
11967  else
11968  setSelection(mSelection+newSelection);
11969  }
11970  } else
11971  setSelection(newSelection);
11972  if (selectionStateChanged)
11973  *selectionStateChanged = mSelection != selectionBefore;
11974  }
11975 }
11976 
11977 /* inherits documentation from base class */
11978 void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged)
11979 {
11980  if (mSelectable != QCP::stNone)
11981  {
11982  QCPDataSelection selectionBefore = mSelection;
11984  if (selectionStateChanged)
11985  *selectionStateChanged = mSelection != selectionBefore;
11986  }
11987 }
11988 /* end of 'src/plottable.cpp' */
11989 
11990 
11991 /* including file 'src/item.cpp' */
11992 /* modified 2021-03-29T02:30:44, size 49486 */
11993 
11997 
12019 /* start documentation of inline functions */
12020 
12031 /* end documentation of inline functions */
12032 
12038 QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name, int anchorId) :
12039  mName(name),
12040  mParentPlot(parentPlot),
12041  mParentItem(parentItem),
12042  mAnchorId(anchorId)
12043 {
12044 }
12045 
12047 {
12048  // unregister as parent at children:
12049  foreach (QCPItemPosition *child, mChildrenX.values())
12050  {
12051  if (child->parentAnchorX() == this)
12052  child->setParentAnchorX(nullptr); // this acts back on this anchor and child removes itself from mChildrenX
12053  }
12054  foreach (QCPItemPosition *child, mChildrenY.values())
12055  {
12056  if (child->parentAnchorY() == this)
12057  child->setParentAnchorY(nullptr); // this acts back on this anchor and child removes itself from mChildrenY
12058  }
12059 }
12060 
12068 {
12069  if (mParentItem)
12070  {
12071  if (mAnchorId > -1)
12072  {
12074  } else
12075  {
12076  qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId;
12077  return {};
12078  }
12079  } else
12080  {
12081  qDebug() << Q_FUNC_INFO << "no parent item set";
12082  return {};
12083  }
12084 }
12085 
12095 {
12096  if (!mChildrenX.contains(pos))
12097  mChildrenX.insert(pos);
12098  else
12099  qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
12100 }
12101 
12109 {
12110  if (!mChildrenX.remove(pos))
12111  qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
12112 }
12113 
12123 {
12124  if (!mChildrenY.contains(pos))
12125  mChildrenY.insert(pos);
12126  else
12127  qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast<quintptr>(pos);
12128 }
12129 
12137 {
12138  if (!mChildrenY.remove(pos))
12139  qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast<quintptr>(pos);
12140 }
12141 
12142 
12146 
12182 /* start documentation of inline functions */
12183 
12205 /* end documentation of inline functions */
12206 
12212 QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name) :
12213  QCPItemAnchor(parentPlot, parentItem, name),
12214  mPositionTypeX(ptAbsolute),
12215  mPositionTypeY(ptAbsolute),
12216  mKey(0),
12217  mValue(0),
12218  mParentAnchorX(nullptr),
12219  mParentAnchorY(nullptr)
12220 {
12221 }
12222 
12224 {
12225  // unregister as parent at children:
12226  // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then
12227  // the setParentAnchor(0) call the correct QCPItemPosition::pixelPosition function instead of QCPItemAnchor::pixelPosition
12228  foreach (QCPItemPosition *child, mChildrenX.values())
12229  {
12230  if (child->parentAnchorX() == this)
12231  child->setParentAnchorX(nullptr); // this acts back on this anchor and child removes itself from mChildrenX
12232  }
12233  foreach (QCPItemPosition *child, mChildrenY.values())
12234  {
12235  if (child->parentAnchorY() == this)
12236  child->setParentAnchorY(nullptr); // this acts back on this anchor and child removes itself from mChildrenY
12237  }
12238  // unregister as child in parent:
12239  if (mParentAnchorX)
12241  if (mParentAnchorY)
12243 }
12244 
12245 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
12247 {
12248  return mAxisRect.data();
12249 }
12250 
12277 {
12278  setTypeX(type);
12279  setTypeY(type);
12280 }
12281 
12290 {
12291  if (mPositionTypeX != type)
12292  {
12293  // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
12294  // were deleted), don't try to recover the pixelPosition() because it would output a qDebug warning.
12295  bool retainPixelPosition = true;
12297  retainPixelPosition = false;
12299  retainPixelPosition = false;
12300 
12301  QPointF pixel;
12302  if (retainPixelPosition)
12303  pixel = pixelPosition();
12304 
12305  mPositionTypeX = type;
12306 
12307  if (retainPixelPosition)
12308  setPixelPosition(pixel);
12309  }
12310 }
12311 
12320 {
12321  if (mPositionTypeY != type)
12322  {
12323  // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect
12324  // were deleted), don't try to recover the pixelPosition() because it would output a qDebug warning.
12325  bool retainPixelPosition = true;
12327  retainPixelPosition = false;
12329  retainPixelPosition = false;
12330 
12331  QPointF pixel;
12332  if (retainPixelPosition)
12333  pixel = pixelPosition();
12334 
12335  mPositionTypeY = type;
12336 
12337  if (retainPixelPosition)
12338  setPixelPosition(pixel);
12339  }
12340 }
12341 
12360 bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
12361 {
12362  bool successX = setParentAnchorX(parentAnchor, keepPixelPosition);
12363  bool successY = setParentAnchorY(parentAnchor, keepPixelPosition);
12364  return successX && successY;
12365 }
12366 
12374 bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
12375 {
12376  // make sure self is not assigned as parent:
12377  if (parentAnchor == this)
12378  {
12379  qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
12380  return false;
12381  }
12382  // make sure no recursive parent-child-relationships are created:
12383  QCPItemAnchor *currentParent = parentAnchor;
12384  while (currentParent)
12385  {
12386  if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
12387  {
12388  // is a QCPItemPosition, might have further parent, so keep iterating
12389  if (currentParentPos == this)
12390  {
12391  qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
12392  return false;
12393  }
12394  currentParent = currentParentPos->parentAnchorX();
12395  } else
12396  {
12397  // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
12398  // same, to prevent a position being child of an anchor which itself depends on the position,
12399  // because they're both on the same item:
12400  if (currentParent->mParentItem == mParentItem)
12401  {
12402  qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
12403  return false;
12404  }
12405  break;
12406  }
12407  }
12408 
12409  // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
12412 
12413  // save pixel position:
12414  QPointF pixelP;
12415  if (keepPixelPosition)
12416  pixelP = pixelPosition();
12417  // unregister at current parent anchor:
12418  if (mParentAnchorX)
12420  // register at new parent anchor:
12421  if (parentAnchor)
12422  parentAnchor->addChildX(this);
12424  // restore pixel position under new parent:
12425  if (keepPixelPosition)
12426  setPixelPosition(pixelP);
12427  else
12428  setCoords(0, coords().y());
12429  return true;
12430 }
12431 
12439 bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
12440 {
12441  // make sure self is not assigned as parent:
12442  if (parentAnchor == this)
12443  {
12444  qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast<quintptr>(parentAnchor);
12445  return false;
12446  }
12447  // make sure no recursive parent-child-relationships are created:
12448  QCPItemAnchor *currentParent = parentAnchor;
12449  while (currentParent)
12450  {
12451  if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition())
12452  {
12453  // is a QCPItemPosition, might have further parent, so keep iterating
12454  if (currentParentPos == this)
12455  {
12456  qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast<quintptr>(parentAnchor);
12457  return false;
12458  }
12459  currentParent = currentParentPos->parentAnchorY();
12460  } else
12461  {
12462  // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the
12463  // same, to prevent a position being child of an anchor which itself depends on the position,
12464  // because they're both on the same item:
12465  if (currentParent->mParentItem == mParentItem)
12466  {
12467  qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast<quintptr>(parentAnchor);
12468  return false;
12469  }
12470  break;
12471  }
12472  }
12473 
12474  // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute:
12477 
12478  // save pixel position:
12479  QPointF pixelP;
12480  if (keepPixelPosition)
12481  pixelP = pixelPosition();
12482  // unregister at current parent anchor:
12483  if (mParentAnchorY)
12485  // register at new parent anchor:
12486  if (parentAnchor)
12487  parentAnchor->addChildY(this);
12489  // restore pixel position under new parent:
12490  if (keepPixelPosition)
12491  setPixelPosition(pixelP);
12492  else
12493  setCoords(coords().x(), 0);
12494  return true;
12495 }
12496 
12514 void QCPItemPosition::setCoords(double key, double value)
12515 {
12516  mKey = key;
12517  mValue = value;
12518 }
12519 
12525 void QCPItemPosition::setCoords(const QPointF &pos)
12526 {
12527  setCoords(pos.x(), pos.y());
12528 }
12529 
12537 {
12538  QPointF result;
12539 
12540  // determine X:
12541  switch (mPositionTypeX)
12542  {
12543  case ptAbsolute:
12544  {
12545  result.rx() = mKey;
12546  if (mParentAnchorX)
12547  result.rx() += mParentAnchorX->pixelPosition().x();
12548  break;
12549  }
12550  case ptViewportRatio:
12551  {
12552  result.rx() = mKey*mParentPlot->viewport().width();
12553  if (mParentAnchorX)
12554  result.rx() += mParentAnchorX->pixelPosition().x();
12555  else
12556  result.rx() += mParentPlot->viewport().left();
12557  break;
12558  }
12559  case ptAxisRectRatio:
12560  {
12561  if (mAxisRect)
12562  {
12563  result.rx() = mKey*mAxisRect.data()->width();
12564  if (mParentAnchorX)
12565  result.rx() += mParentAnchorX->pixelPosition().x();
12566  else
12567  result.rx() += mAxisRect.data()->left();
12568  } else
12569  qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
12570  break;
12571  }
12572  case ptPlotCoords:
12573  {
12574  if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
12575  result.rx() = mKeyAxis.data()->coordToPixel(mKey);
12576  else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
12577  result.rx() = mValueAxis.data()->coordToPixel(mValue);
12578  else
12579  qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
12580  break;
12581  }
12582  }
12583 
12584  // determine Y:
12585  switch (mPositionTypeY)
12586  {
12587  case ptAbsolute:
12588  {
12589  result.ry() = mValue;
12590  if (mParentAnchorY)
12591  result.ry() += mParentAnchorY->pixelPosition().y();
12592  break;
12593  }
12594  case ptViewportRatio:
12595  {
12596  result.ry() = mValue*mParentPlot->viewport().height();
12597  if (mParentAnchorY)
12598  result.ry() += mParentAnchorY->pixelPosition().y();
12599  else
12600  result.ry() += mParentPlot->viewport().top();
12601  break;
12602  }
12603  case ptAxisRectRatio:
12604  {
12605  if (mAxisRect)
12606  {
12607  result.ry() = mValue*mAxisRect.data()->height();
12608  if (mParentAnchorY)
12609  result.ry() += mParentAnchorY->pixelPosition().y();
12610  else
12611  result.ry() += mAxisRect.data()->top();
12612  } else
12613  qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
12614  break;
12615  }
12616  case ptPlotCoords:
12617  {
12618  if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
12619  result.ry() = mKeyAxis.data()->coordToPixel(mKey);
12620  else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
12621  result.ry() = mValueAxis.data()->coordToPixel(mValue);
12622  else
12623  qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
12624  break;
12625  }
12626  }
12627 
12628  return result;
12629 }
12630 
12636 void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis)
12637 {
12638  mKeyAxis = keyAxis;
12640 }
12641 
12648 {
12649  mAxisRect = axisRect;
12650 }
12651 
12662 void QCPItemPosition::setPixelPosition(const QPointF &pixelPosition)
12663 {
12664  double x = pixelPosition.x();
12665  double y = pixelPosition.y();
12666 
12667  switch (mPositionTypeX)
12668  {
12669  case ptAbsolute:
12670  {
12671  if (mParentAnchorX)
12672  x -= mParentAnchorX->pixelPosition().x();
12673  break;
12674  }
12675  case ptViewportRatio:
12676  {
12677  if (mParentAnchorX)
12678  x -= mParentAnchorX->pixelPosition().x();
12679  else
12680  x -= mParentPlot->viewport().left();
12681  x /= double(mParentPlot->viewport().width());
12682  break;
12683  }
12684  case ptAxisRectRatio:
12685  {
12686  if (mAxisRect)
12687  {
12688  if (mParentAnchorX)
12689  x -= mParentAnchorX->pixelPosition().x();
12690  else
12691  x -= mAxisRect.data()->left();
12692  x /= double(mAxisRect.data()->width());
12693  } else
12694  qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined";
12695  break;
12696  }
12697  case ptPlotCoords:
12698  {
12699  if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal)
12700  x = mKeyAxis.data()->pixelToCoord(x);
12701  else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal)
12702  y = mValueAxis.data()->pixelToCoord(x);
12703  else
12704  qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined";
12705  break;
12706  }
12707  }
12708 
12709  switch (mPositionTypeY)
12710  {
12711  case ptAbsolute:
12712  {
12713  if (mParentAnchorY)
12714  y -= mParentAnchorY->pixelPosition().y();
12715  break;
12716  }
12717  case ptViewportRatio:
12718  {
12719  if (mParentAnchorY)
12720  y -= mParentAnchorY->pixelPosition().y();
12721  else
12722  y -= mParentPlot->viewport().top();
12723  y /= double(mParentPlot->viewport().height());
12724  break;
12725  }
12726  case ptAxisRectRatio:
12727  {
12728  if (mAxisRect)
12729  {
12730  if (mParentAnchorY)
12731  y -= mParentAnchorY->pixelPosition().y();
12732  else
12733  y -= mAxisRect.data()->top();
12734  y /= double(mAxisRect.data()->height());
12735  } else
12736  qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined";
12737  break;
12738  }
12739  case ptPlotCoords:
12740  {
12741  if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical)
12742  x = mKeyAxis.data()->pixelToCoord(y);
12743  else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical)
12744  y = mValueAxis.data()->pixelToCoord(y);
12745  else
12746  qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined";
12747  break;
12748  }
12749  }
12750 
12751  setCoords(x, y);
12752 }
12753 
12754 
12758 
12884 /* start of documentation of inline functions */
12885 
12901 /* end of documentation of inline functions */
12902 /* start documentation of pure virtual functions */
12903 
12914 /* end documentation of pure virtual functions */
12915 /* start documentation of signals */
12916 
12922 /* end documentation of signals */
12923 
12928  QCPLayerable(parentPlot),
12929  mClipToAxisRect(false),
12930  mSelectable(true),
12931  mSelected(false)
12932 {
12933  parentPlot->registerItem(this);
12934 
12935  QList<QCPAxisRect*> rects = parentPlot->axisRects();
12936  if (!rects.isEmpty())
12937  {
12938  setClipToAxisRect(true);
12939  setClipAxisRect(rects.first());
12940  }
12941 }
12942 
12944 {
12945  // don't delete mPositions because every position is also an anchor and thus in mAnchors
12946  qDeleteAll(mAnchors);
12947 }
12948 
12949 /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */
12951 {
12952  return mClipAxisRect.data();
12953 }
12954 
12962 {
12963  mClipToAxisRect = clip;
12964  if (mClipToAxisRect)
12966 }
12967 
12975 {
12976  mClipAxisRect = rect;
12977  if (mClipToAxisRect)
12979 }
12980 
12990 void QCPAbstractItem::setSelectable(bool selectable)
12991 {
12992  if (mSelectable != selectable)
12993  {
12996  }
12997 }
12998 
13013 void QCPAbstractItem::setSelected(bool selected)
13014 {
13015  if (mSelected != selected)
13016  {
13017  mSelected = selected;
13019  }
13020 }
13021 
13032 QCPItemPosition *QCPAbstractItem::position(const QString &name) const
13033 {
13034  foreach (QCPItemPosition *position, mPositions)
13035  {
13036  if (position->name() == name)
13037  return position;
13038  }
13039  qDebug() << Q_FUNC_INFO << "position with name not found:" << name;
13040  return nullptr;
13041 }
13042 
13053 QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const
13054 {
13055  foreach (QCPItemAnchor *anchor, mAnchors)
13056  {
13057  if (anchor->name() == name)
13058  return anchor;
13059  }
13060  qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name;
13061  return nullptr;
13062 }
13063 
13072 bool QCPAbstractItem::hasAnchor(const QString &name) const
13073 {
13074  foreach (QCPItemAnchor *anchor, mAnchors)
13075  {
13076  if (anchor->name() == name)
13077  return true;
13078  }
13079  return false;
13080 }
13081 
13092 {
13094  return mClipAxisRect.data()->rect();
13095  else
13096  return mParentPlot->viewport();
13097 }
13098 
13113 {
13115 }
13116 
13130 double QCPAbstractItem::rectDistance(const QRectF &rect, const QPointF &pos, bool filledRect) const
13131 {
13132  double result = -1;
13133 
13134  // distance to border:
13135  const QList<QLineF> lines = QList<QLineF>() << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight())
13136  << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight());
13137  const QCPVector2D posVec(pos);
13138  double minDistSqr = (std::numeric_limits<double>::max)();
13139  foreach (const QLineF &line, lines)
13140  {
13141  double distSqr = posVec.distanceSquaredToLine(line.p1(), line.p2());
13142  if (distSqr < minDistSqr)
13143  minDistSqr = distSqr;
13144  }
13145  result = qSqrt(minDistSqr);
13146 
13147  // filled rect, allow click inside to count as hit:
13148  if (filledRect && result > mParentPlot->selectionTolerance()*0.99)
13149  {
13150  if (rect.contains(pos))
13151  result = mParentPlot->selectionTolerance()*0.99;
13152  }
13153  return result;
13154 }
13155 
13166 QPointF QCPAbstractItem::anchorPixelPosition(int anchorId) const
13167 {
13168  qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId;
13169  return {};
13170 }
13171 
13187 {
13188  if (hasAnchor(name))
13189  qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
13190  QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name);
13191  mPositions.append(newPosition);
13192  mAnchors.append(newPosition); // every position is also an anchor
13193  newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis);
13194  newPosition->setType(QCPItemPosition::ptPlotCoords);
13195  if (mParentPlot->axisRect())
13196  newPosition->setAxisRect(mParentPlot->axisRect());
13197  newPosition->setCoords(0, 0);
13198  return newPosition;
13199 }
13200 
13220 QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId)
13221 {
13222  if (hasAnchor(name))
13223  qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name;
13224  QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId);
13225  mAnchors.append(newAnchor);
13226  return newAnchor;
13227 }
13228 
13229 /* inherits documentation from base class */
13230 void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
13231 {
13232  Q_UNUSED(event)
13233  Q_UNUSED(details)
13234  if (mSelectable)
13235  {
13236  bool selBefore = mSelected;
13237  setSelected(additive ? !mSelected : true);
13238  if (selectionStateChanged)
13239  *selectionStateChanged = mSelected != selBefore;
13240  }
13241 }
13242 
13243 /* inherits documentation from base class */
13244 void QCPAbstractItem::deselectEvent(bool *selectionStateChanged)
13245 {
13246  if (mSelectable)
13247  {
13248  bool selBefore = mSelected;
13249  setSelected(false);
13250  if (selectionStateChanged)
13251  *selectionStateChanged = mSelected != selBefore;
13252  }
13253 }
13254 
13255 /* inherits documentation from base class */
13257 {
13258  return QCP::iSelectItems;
13259 }
13260 /* end of 'src/item.cpp' */
13261 
13262 
13263 /* including file 'src/core.cpp' */
13264 /* modified 2021-03-29T02:30:44, size 127198 */
13265 
13269 
13279 /* start of documentation of inline functions */
13280 
13295 /* end of documentation of inline functions */
13296 /* start of documentation of signals */
13297 
13489 /* end of documentation of signals */
13490 /* start of documentation of public members */
13491 
13588 /* end of documentation of public members */
13589 
13593 QCustomPlot::QCustomPlot(QWidget *parent) :
13594  QWidget(parent),
13595  xAxis(nullptr),
13596  yAxis(nullptr),
13597  xAxis2(nullptr),
13598  yAxis2(nullptr),
13599  legend(nullptr),
13600  mBufferDevicePixelRatio(1.0), // will be adapted to primary screen below
13601  mPlotLayout(nullptr),
13602  mAutoAddPlottableToLegend(true),
13603  mAntialiasedElements(QCP::aeNone),
13604  mNotAntialiasedElements(QCP::aeNone),
13605  mInteractions(QCP::iNone),
13606  mSelectionTolerance(8),
13607  mNoAntialiasingOnDrag(false),
13608  mBackgroundBrush(Qt::white, Qt::SolidPattern),
13609  mBackgroundScaled(true),
13610  mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
13611  mCurrentLayer(nullptr),
13612  mPlottingHints(QCP::phCacheLabels|QCP::phImmediateRefresh),
13613  mMultiSelectModifier(Qt::ControlModifier),
13614  mSelectionRectMode(QCP::srmNone),
13615  mSelectionRect(nullptr),
13616  mOpenGl(false),
13617  mMouseHasMoved(false),
13618  mMouseEventLayerable(nullptr),
13619  mMouseSignalLayerable(nullptr),
13620  mReplotting(false),
13621  mReplotQueued(false),
13622  mReplotTime(0),
13623  mReplotTimeAverage(0),
13624  mOpenGlMultisamples(16),
13625  mOpenGlAntialiasedElementsBackup(QCP::aeNone),
13626  mOpenGlCacheLabelsBackup(true)
13627 {
13628  setAttribute(Qt::WA_NoMousePropagation);
13629  setAttribute(Qt::WA_OpaquePaintEvent);
13630  setFocusPolicy(Qt::ClickFocus);
13631  setMouseTracking(true);
13632  QLocale currentLocale = locale();
13633  currentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
13634  setLocale(currentLocale);
13635 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
13636 # ifdef QCP_DEVICEPIXELRATIO_FLOAT
13637  setBufferDevicePixelRatio(QWidget::devicePixelRatioF());
13638 # else
13639  setBufferDevicePixelRatio(QWidget::devicePixelRatio());
13640 # endif
13641 #endif
13642 
13645  // create initial layers:
13646  mLayers.append(new QCPLayer(this, QLatin1String("background")));
13647  mLayers.append(new QCPLayer(this, QLatin1String("grid")));
13648  mLayers.append(new QCPLayer(this, QLatin1String("main")));
13649  mLayers.append(new QCPLayer(this, QLatin1String("axes")));
13650  mLayers.append(new QCPLayer(this, QLatin1String("legend")));
13651  mLayers.append(new QCPLayer(this, QLatin1String("overlay")));
13653  setCurrentLayer(QLatin1String("main"));
13654  layer(QLatin1String("overlay"))->setMode(QCPLayer::lmBuffered);
13655 
13656  // create initial layout, axis rect and legend:
13657  mPlotLayout = new QCPLayoutGrid;
13659  mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry
13660  mPlotLayout->setLayer(QLatin1String("main"));
13661  QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true);
13662  mPlotLayout->addElement(0, 0, defaultAxisRect);
13663  xAxis = defaultAxisRect->axis(QCPAxis::atBottom);
13664  yAxis = defaultAxisRect->axis(QCPAxis::atLeft);
13665  xAxis2 = defaultAxisRect->axis(QCPAxis::atTop);
13666  yAxis2 = defaultAxisRect->axis(QCPAxis::atRight);
13667  legend = new QCPLegend;
13668  legend->setVisible(false);
13669  defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop);
13670  defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12));
13671 
13672  defaultAxisRect->setLayer(QLatin1String("background"));
13673  xAxis->setLayer(QLatin1String("axes"));
13674  yAxis->setLayer(QLatin1String("axes"));
13675  xAxis2->setLayer(QLatin1String("axes"));
13676  yAxis2->setLayer(QLatin1String("axes"));
13677  xAxis->grid()->setLayer(QLatin1String("grid"));
13678  yAxis->grid()->setLayer(QLatin1String("grid"));
13679  xAxis2->grid()->setLayer(QLatin1String("grid"));
13680  yAxis2->grid()->setLayer(QLatin1String("grid"));
13681  legend->setLayer(QLatin1String("legend"));
13682 
13683  // create selection rect instance:
13684  mSelectionRect = new QCPSelectionRect(this);
13685  mSelectionRect->setLayer(QLatin1String("overlay"));
13686 
13687  setViewport(rect()); // needs to be called after mPlotLayout has been created
13688 
13690 }
13691 
13693 {
13694  clearPlottables();
13695  clearItems();
13696 
13697  if (mPlotLayout)
13698  {
13699  delete mPlotLayout;
13700  mPlotLayout = nullptr;
13701  }
13702 
13703  mCurrentLayer = nullptr;
13704  qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed
13705  mLayers.clear();
13706 }
13707 
13725 void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements)
13726 {
13728 
13729  // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
13732 }
13733 
13741 void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled)
13742 {
13743  if (!enabled && mAntialiasedElements.testFlag(antialiasedElement))
13744  mAntialiasedElements &= ~antialiasedElement;
13745  else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement))
13746  mAntialiasedElements |= antialiasedElement;
13747 
13748  // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
13751 }
13752 
13771 void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements &notAntialiasedElements)
13772 {
13774 
13775  // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
13778 }
13779 
13787 void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled)
13788 {
13789  if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement))
13790  mNotAntialiasedElements &= ~notAntialiasedElement;
13791  else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement))
13792  mNotAntialiasedElements |= notAntialiasedElement;
13793 
13794  // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously:
13797 }
13798 
13806 {
13808 }
13809 
13864 void QCustomPlot::setInteractions(const QCP::Interactions &interactions)
13865 {
13867 }
13868 
13876 void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled)
13877 {
13878  if (!enabled && mInteractions.testFlag(interaction))
13879  mInteractions &= ~interaction;
13880  else if (enabled && !mInteractions.testFlag(interaction))
13881  mInteractions |= interaction;
13882 }
13883 
13898 {
13899  mSelectionTolerance = pixels;
13900 }
13901 
13912 {
13913  mNoAntialiasingOnDrag = enabled;
13914 }
13915 
13921 void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints)
13922 {
13923  mPlottingHints = hints;
13924 }
13925 
13932 {
13933  QCP::PlottingHints newHints = mPlottingHints;
13934  if (!enabled)
13935  newHints &= ~hint;
13936  else
13937  newHints |= hint;
13938 
13939  if (newHints != mPlottingHints)
13940  setPlottingHints(newHints);
13941 }
13942 
13953 void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier)
13954 {
13955  mMultiSelectModifier = modifier;
13956 }
13957 
13979 {
13980  if (mSelectionRect)
13981  {
13982  if (mode == QCP::srmNone)
13983  mSelectionRect->cancel(); // when switching to none, we immediately want to abort a potentially active selection rect
13984 
13985  // disconnect old connections:
13987  disconnect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectSelection(QRect,QMouseEvent*)));
13988  else if (mSelectionRectMode == QCP::srmZoom)
13989  disconnect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectZoom(QRect,QMouseEvent*)));
13990 
13991  // establish new ones:
13992  if (mode == QCP::srmSelect)
13993  connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectSelection(QRect,QMouseEvent*)));
13994  else if (mode == QCP::srmZoom)
13995  connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectZoom(QRect,QMouseEvent*)));
13996  }
13997 
13998  mSelectionRectMode = mode;
13999 }
14000 
14012 {
14013  delete mSelectionRect;
14014 
14016 
14017  if (mSelectionRect)
14018  {
14019  // establish connections with new selection rect:
14021  connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectSelection(QRect,QMouseEvent*)));
14022  else if (mSelectionRectMode == QCP::srmZoom)
14023  connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectZoom(QRect,QMouseEvent*)));
14024  }
14025 }
14026 
14063 void QCustomPlot::setOpenGl(bool enabled, int multisampling)
14064 {
14065  mOpenGlMultisamples = qMax(0, multisampling);
14066 #ifdef QCUSTOMPLOT_USE_OPENGL
14067  mOpenGl = enabled;
14068  if (mOpenGl)
14069  {
14070  if (setupOpenGl())
14071  {
14072  // backup antialiasing override and labelcaching setting so we can restore upon disabling OpenGL
14075  // set antialiasing override to antialias all (aligns gl pixel grid properly), and disable label caching (would use software rasterizer for pixmap caches):
14078  } else
14079  {
14080  qDebug() << Q_FUNC_INFO << "Failed to enable OpenGL, continuing plotting without hardware acceleration.";
14081  mOpenGl = false;
14082  }
14083  } else
14084  {
14085  // restore antialiasing override and labelcaching to what it was before enabling OpenGL, if nobody changed it in the meantime:
14088  if (!mPlottingHints.testFlag(QCP::phCacheLabels))
14090  freeOpenGl();
14091  }
14092  // recreate all paint buffers:
14093  mPaintBuffers.clear();
14095 #else
14096  Q_UNUSED(enabled)
14097  qDebug() << Q_FUNC_INFO << "QCustomPlot can't use OpenGL because QCUSTOMPLOT_USE_OPENGL was not defined during compilation (add 'DEFINES += QCUSTOMPLOT_USE_OPENGL' to your qmake .pro file)";
14098 #endif
14099 }
14100 
14117 void QCustomPlot::setViewport(const QRect &rect)
14118 {
14119  mViewport = rect;
14120  if (mPlotLayout)
14122 }
14123 
14136 {
14137  if (!qFuzzyCompare(ratio, mBufferDevicePixelRatio))
14138  {
14139 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
14140  mBufferDevicePixelRatio = ratio;
14141  foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer, mPaintBuffers)
14142  buffer->setDevicePixelRatio(mBufferDevicePixelRatio);
14143  // Note: axis label cache has devicePixelRatio as part of cache hash, so no need to manually clear cache here
14144 #else
14145  qDebug() << Q_FUNC_INFO << "Device pixel ratios not supported for Qt versions before 5.4";
14147 #endif
14148  }
14149 }
14150 
14166 void QCustomPlot::setBackground(const QPixmap &pm)
14167 {
14168  mBackgroundPixmap = pm;
14169  mScaledBackgroundPixmap = QPixmap();
14170 }
14171 
14185 void QCustomPlot::setBackground(const QBrush &brush)
14186 {
14187  mBackgroundBrush = brush;
14188 }
14189 
14197 void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
14198 {
14199  mBackgroundPixmap = pm;
14200  mScaledBackgroundPixmap = QPixmap();
14201  mBackgroundScaled = scaled;
14202  mBackgroundScaledMode = mode;
14203 }
14204 
14216 {
14217  mBackgroundScaled = scaled;
14218 }
14219 
14226 void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode)
14227 {
14228  mBackgroundScaledMode = mode;
14229 }
14230 
14240 {
14241  if (index >= 0 && index < mPlottables.size())
14242  {
14243  return mPlottables.at(index);
14244  } else
14245  {
14246  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
14247  return nullptr;
14248  }
14249 }
14250 
14259 {
14260  if (!mPlottables.isEmpty())
14261  {
14262  return mPlottables.last();
14263  } else
14264  return nullptr;
14265 }
14266 
14276 {
14277  if (!mPlottables.contains(plottable))
14278  {
14279  qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast<quintptr>(plottable);
14280  return false;
14281  }
14282 
14283  // remove plottable from legend:
14285  // special handling for QCPGraphs to maintain the simple graph interface:
14286  if (QCPGraph *graph = qobject_cast<QCPGraph*>(plottable))
14287  mGraphs.removeOne(graph);
14288  // remove plottable:
14289  delete plottable;
14290  mPlottables.removeOne(plottable);
14291  return true;
14292 }
14293 
14299 {
14300  if (index >= 0 && index < mPlottables.size())
14301  return removePlottable(mPlottables[index]);
14302  else
14303  {
14304  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
14305  return false;
14306  }
14307 }
14308 
14318 {
14319  int c = mPlottables.size();
14320  for (int i=c-1; i >= 0; --i)
14322  return c;
14323 }
14324 
14331 {
14332  return mPlottables.size();
14333 }
14334 
14342 QList<QCPAbstractPlottable*> QCustomPlot::selectedPlottables() const
14343 {
14344  QList<QCPAbstractPlottable*> result;
14346  {
14347  if (plottable->selected())
14348  result.append(plottable);
14349  }
14350  return result;
14351 }
14352 
14362 QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable, int *dataIndex) const
14363 {
14364  return plottableAt<QCPAbstractPlottable>(pos, onlySelectable, dataIndex);
14365 }
14366 
14371 {
14372  return mPlottables.contains(plottable);
14373 }
14374 
14383 QCPGraph *QCustomPlot::graph(int index) const
14384 {
14385  if (index >= 0 && index < mGraphs.size())
14386  {
14387  return mGraphs.at(index);
14388  } else
14389  {
14390  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
14391  return nullptr;
14392  }
14393 }
14394 
14403 {
14404  if (!mGraphs.isEmpty())
14405  {
14406  return mGraphs.last();
14407  } else
14408  return nullptr;
14409 }
14410 
14424 {
14425  if (!keyAxis) keyAxis = xAxis;
14426  if (!valueAxis) valueAxis = yAxis;
14427  if (!keyAxis || !valueAxis)
14428  {
14429  qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
14430  return nullptr;
14431  }
14432  if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this)
14433  {
14434  qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
14435  return nullptr;
14436  }
14437 
14438  QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis);
14439  newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size()));
14440  return newGraph;
14441 }
14442 
14454 {
14455  return removePlottable(graph);
14456 }
14457 
14463 {
14464  if (index >= 0 && index < mGraphs.size())
14465  return removeGraph(mGraphs[index]);
14466  else
14467  return false;
14468 }
14469 
14479 {
14480  int c = mGraphs.size();
14481  for (int i=c-1; i >= 0; --i)
14482  removeGraph(mGraphs[i]);
14483  return c;
14484 }
14485 
14492 {
14493  return mGraphs.size();
14494 }
14495 
14504 QList<QCPGraph*> QCustomPlot::selectedGraphs() const
14505 {
14506  QList<QCPGraph*> result;
14507  foreach (QCPGraph *graph, mGraphs)
14508  {
14509  if (graph->selected())
14510  result.append(graph);
14511  }
14512  return result;
14513 }
14514 
14524 {
14525  if (index >= 0 && index < mItems.size())
14526  {
14527  return mItems.at(index);
14528  } else
14529  {
14530  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
14531  return nullptr;
14532  }
14533 }
14534 
14543 {
14544  if (!mItems.isEmpty())
14545  {
14546  return mItems.last();
14547  } else
14548  return nullptr;
14549 }
14550 
14559 {
14560  if (mItems.contains(item))
14561  {
14562  delete item;
14563  mItems.removeOne(item);
14564  return true;
14565  } else
14566  {
14567  qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast<quintptr>(item);
14568  return false;
14569  }
14570 }
14571 
14577 {
14578  if (index >= 0 && index < mItems.size())
14579  return removeItem(mItems[index]);
14580  else
14581  {
14582  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
14583  return false;
14584  }
14585 }
14586 
14595 {
14596  int c = mItems.size();
14597  for (int i=c-1; i >= 0; --i)
14598  removeItem(mItems[i]);
14599  return c;
14600 }
14601 
14608 {
14609  return mItems.size();
14610 }
14611 
14617 QList<QCPAbstractItem*> QCustomPlot::selectedItems() const
14618 {
14619  QList<QCPAbstractItem*> result;
14620  foreach (QCPAbstractItem *item, mItems)
14621  {
14622  if (item->selected())
14623  result.append(item);
14624  }
14625  return result;
14626 }
14627 
14637 QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const
14638 {
14639  return itemAt<QCPAbstractItem>(pos, onlySelectable);
14640 }
14641 
14648 {
14649  return mItems.contains(item);
14650 }
14651 
14660 QCPLayer *QCustomPlot::layer(const QString &name) const
14661 {
14662  foreach (QCPLayer *layer, mLayers)
14663  {
14664  if (layer->name() == name)
14665  return layer;
14666  }
14667  return nullptr;
14668 }
14669 
14676 QCPLayer *QCustomPlot::layer(int index) const
14677 {
14678  if (index >= 0 && index < mLayers.size())
14679  {
14680  return mLayers.at(index);
14681  } else
14682  {
14683  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
14684  return nullptr;
14685  }
14686 }
14687 
14692 {
14693  return mCurrentLayer;
14694 }
14695 
14706 bool QCustomPlot::setCurrentLayer(const QString &name)
14707 {
14708  if (QCPLayer *newCurrentLayer = layer(name))
14709  {
14710  return setCurrentLayer(newCurrentLayer);
14711  } else
14712  {
14713  qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name;
14714  return false;
14715  }
14716 }
14717 
14727 {
14728  if (!mLayers.contains(layer))
14729  {
14730  qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
14731  return false;
14732  }
14733 
14734  mCurrentLayer = layer;
14735  return true;
14736 }
14737 
14744 {
14745  return mLayers.size();
14746 }
14747 
14761 bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode)
14762 {
14763  if (!otherLayer)
14764  otherLayer = mLayers.last();
14765  if (!mLayers.contains(otherLayer))
14766  {
14767  qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
14768  return false;
14769  }
14770  if (layer(name))
14771  {
14772  qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name;
14773  return false;
14774  }
14775 
14776  QCPLayer *newLayer = new QCPLayer(this, name);
14777  mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer);
14779  setupPaintBuffers(); // associates new layer with the appropriate paint buffer
14780  return true;
14781 }
14782 
14798 {
14799  if (!mLayers.contains(layer))
14800  {
14801  qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
14802  return false;
14803  }
14804  if (mLayers.size() < 2)
14805  {
14806  qDebug() << Q_FUNC_INFO << "can't remove last layer";
14807  return false;
14808  }
14809 
14810  // append all children of this layer to layer below (if this is lowest layer, prepend to layer above)
14811  int removedIndex = layer->index();
14812  bool isFirstLayer = removedIndex==0;
14813  QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1);
14814  QList<QCPLayerable*> children = layer->children();
14815  if (isFirstLayer) // prepend in reverse order (such that relative order stays the same)
14816  std::reverse(children.begin(), children.end());
14817  foreach (QCPLayerable *child, children)
14818  child->moveToLayer(targetLayer, isFirstLayer); // prepend if isFirstLayer, otherwise append
14819 
14820  // if removed layer is current layer, change current layer to layer below/above:
14821  if (layer == mCurrentLayer)
14822  setCurrentLayer(targetLayer);
14823 
14824  // invalidate the paint buffer that was responsible for this layer:
14825  if (QSharedPointer<QCPAbstractPaintBuffer> pb = layer->mPaintBuffer.toStrongRef())
14826  pb->setInvalidated();
14827 
14828  // remove layer:
14829  delete layer;
14830  mLayers.removeOne(layer);
14832  return true;
14833 }
14834 
14845 {
14846  if (!mLayers.contains(layer))
14847  {
14848  qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(layer);
14849  return false;
14850  }
14851  if (!mLayers.contains(otherLayer))
14852  {
14853  qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast<quintptr>(otherLayer);
14854  return false;
14855  }
14856 
14857  if (layer->index() > otherLayer->index())
14858  mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0));
14859  else if (layer->index() < otherLayer->index())
14860  mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 0:-1));
14861 
14862  // invalidate the paint buffers that are responsible for the layers:
14863  if (QSharedPointer<QCPAbstractPaintBuffer> pb = layer->mPaintBuffer.toStrongRef())
14864  pb->setInvalidated();
14865  if (QSharedPointer<QCPAbstractPaintBuffer> pb = otherLayer->mPaintBuffer.toStrongRef())
14866  pb->setInvalidated();
14867 
14869  return true;
14870 }
14871 
14882 {
14883  return axisRects().size();
14884 }
14885 
14906 {
14907  const QList<QCPAxisRect*> rectList = axisRects();
14908  if (index >= 0 && index < rectList.size())
14909  {
14910  return rectList.at(index);
14911  } else
14912  {
14913  qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index;
14914  return nullptr;
14915  }
14916 }
14917 
14929 QList<QCPAxisRect*> QCustomPlot::axisRects() const
14930 {
14931  QList<QCPAxisRect*> result;
14932  QStack<QCPLayoutElement*> elementStack;
14933  if (mPlotLayout)
14934  elementStack.push(mPlotLayout);
14935 
14936  while (!elementStack.isEmpty())
14937  {
14938  foreach (QCPLayoutElement *element, elementStack.pop()->elements(false))
14939  {
14940  if (element)
14941  {
14942  elementStack.push(element);
14943  if (QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(element))
14944  result.append(ar);
14945  }
14946  }
14947  }
14948 
14949  return result;
14950 }
14951 
14962 {
14963  QCPLayoutElement *currentElement = mPlotLayout;
14964  bool searchSubElements = true;
14965  while (searchSubElements && currentElement)
14966  {
14967  searchSubElements = false;
14968  foreach (QCPLayoutElement *subElement, currentElement->elements(false))
14969  {
14970  if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0)
14971  {
14972  currentElement = subElement;
14973  searchSubElements = true;
14974  break;
14975  }
14976  }
14977  }
14978  return currentElement;
14979 }
14980 
14991 QCPAxisRect *QCustomPlot::axisRectAt(const QPointF &pos) const
14992 {
14993  QCPAxisRect *result = nullptr;
14994  QCPLayoutElement *currentElement = mPlotLayout;
14995  bool searchSubElements = true;
14996  while (searchSubElements && currentElement)
14997  {
14998  searchSubElements = false;
14999  foreach (QCPLayoutElement *subElement, currentElement->elements(false))
15000  {
15001  if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0)
15002  {
15003  currentElement = subElement;
15004  searchSubElements = true;
15005  if (QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(currentElement))
15006  result = ar;
15007  break;
15008  }
15009  }
15010  }
15011  return result;
15012 }
15013 
15021 QList<QCPAxis*> QCustomPlot::selectedAxes() const
15022 {
15023  QList<QCPAxis*> result, allAxes;
15024  foreach (QCPAxisRect *rect, axisRects())
15025  allAxes << rect->axes();
15026 
15027  foreach (QCPAxis *axis, allAxes)
15028  {
15029  if (axis->selectedParts() != QCPAxis::spNone)
15030  result.append(axis);
15031  }
15032 
15033  return result;
15034 }
15035 
15043 QList<QCPLegend*> QCustomPlot::selectedLegends() const
15044 {
15045  QList<QCPLegend*> result;
15046 
15047  QStack<QCPLayoutElement*> elementStack;
15048  if (mPlotLayout)
15049  elementStack.push(mPlotLayout);
15050 
15051  while (!elementStack.isEmpty())
15052  {
15053  foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false))
15054  {
15055  if (subElement)
15056  {
15057  elementStack.push(subElement);
15058  if (QCPLegend *leg = qobject_cast<QCPLegend*>(subElement))
15059  {
15060  if (leg->selectedParts() != QCPLegend::spNone)
15061  result.append(leg);
15062  }
15063  }
15064  }
15065  }
15066 
15067  return result;
15068 }
15069 
15080 {
15081  foreach (QCPLayer *layer, mLayers)
15082  {
15083  foreach (QCPLayerable *layerable, layer->children())
15084  layerable->deselectEvent(nullptr);
15085  }
15086 }
15087 
15116 {
15117  if (refreshPriority == QCustomPlot::rpQueuedReplot)
15118  {
15119  if (!mReplotQueued)
15120  {
15121  mReplotQueued = true;
15122  QTimer::singleShot(0, this, SLOT(replot()));
15123  }
15124  return;
15125  }
15126 
15127  if (mReplotting) // incase signals loop back to replot slot
15128  return;
15129  mReplotting = true;
15130  mReplotQueued = false;
15131  emit beforeReplot();
15132 
15133 # if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
15134  QTime replotTimer;
15135  replotTimer.start();
15136 # else
15137  QElapsedTimer replotTimer;
15138  replotTimer.start();
15139 # endif
15140 
15141  updateLayout();
15142  // draw all layered objects (grid, axes, plottables, items, legend,...) into their buffers:
15144  foreach (QCPLayer *layer, mLayers)
15146  foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer, mPaintBuffers)
15147  buffer->setInvalidated(false);
15148 
15149  if ((refreshPriority == rpRefreshHint && mPlottingHints.testFlag(QCP::phImmediateRefresh)) || refreshPriority==rpImmediateRefresh)
15150  repaint();
15151  else
15152  update();
15153 
15154 # if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
15155  mReplotTime = replotTimer.elapsed();
15156 # else
15157  mReplotTime = replotTimer.nsecsElapsed()*1e-6;
15158 # endif
15159  if (!qFuzzyIsNull(mReplotTimeAverage))
15160  mReplotTimeAverage = mReplotTimeAverage*0.9 + mReplotTime*0.1; // exponential moving average with a time constant of 10 last replots
15161  else
15162  mReplotTimeAverage = mReplotTime; // no previous replots to average with, so initialize with replot time
15163 
15164  emit afterReplot();
15165  mReplotting = false;
15166 }
15167 
15174 double QCustomPlot::replotTime(bool average) const
15175 {
15176  return average ? mReplotTimeAverage : mReplotTime;
15177 }
15178 
15187 void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables)
15188 {
15189  QList<QCPAxis*> allAxes;
15190  foreach (QCPAxisRect *rect, axisRects())
15191  allAxes << rect->axes();
15192 
15193  foreach (QCPAxis *axis, allAxes)
15194  axis->rescale(onlyVisiblePlottables);
15195 }
15196 
15234 bool QCustomPlot::savePdf(const QString &fileName, int width, int height, QCP::ExportPen exportPen, const QString &pdfCreator, const QString &pdfTitle)
15235 {
15236  bool success = false;
15237 #ifdef QT_NO_PRINTER
15238  Q_UNUSED(fileName)
15239  Q_UNUSED(exportPen)
15240  Q_UNUSED(width)
15241  Q_UNUSED(height)
15242  Q_UNUSED(pdfCreator)
15243  Q_UNUSED(pdfTitle)
15244  qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created.";
15245 #else
15246  int newWidth, newHeight;
15247  if (width == 0 || height == 0)
15248  {
15249  newWidth = this->width();
15250  newHeight = this->height();
15251  } else
15252  {
15253  newWidth = width;
15254  newHeight = height;
15255  }
15256 
15257  QPrinter printer(QPrinter::ScreenResolution);
15258  printer.setOutputFileName(fileName);
15259  printer.setOutputFormat(QPrinter::PdfFormat);
15260  printer.setColorMode(QPrinter::Color);
15261  printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator);
15262  printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle);
15263  QRect oldViewport = viewport();
15264  setViewport(QRect(0, 0, newWidth, newHeight));
15265 #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
15266  printer.setFullPage(true);
15267  printer.setPaperSize(viewport().size(), QPrinter::DevicePixel);
15268 #else
15269  QPageLayout pageLayout;
15270  pageLayout.setMode(QPageLayout::FullPageMode);
15271  pageLayout.setOrientation(QPageLayout::Portrait);
15272  pageLayout.setMargins(QMarginsF(0, 0, 0, 0));
15273  pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch));
15274  printer.setPageLayout(pageLayout);
15275 #endif
15276  QCPPainter printpainter;
15277  if (printpainter.begin(&printer))
15278  {
15279  printpainter.setMode(QCPPainter::pmVectorized);
15280  printpainter.setMode(QCPPainter::pmNoCaching);
15281  printpainter.setMode(QCPPainter::pmNonCosmetic, exportPen==QCP::epNoCosmetic);
15282  printpainter.setWindow(mViewport);
15283  if (mBackgroundBrush.style() != Qt::NoBrush &&
15284  mBackgroundBrush.color() != Qt::white &&
15285  mBackgroundBrush.color() != Qt::transparent &&
15286  mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent
15287  printpainter.fillRect(viewport(), mBackgroundBrush);
15288  draw(&printpainter);
15289  printpainter.end();
15290  success = true;
15291  }
15292  setViewport(oldViewport);
15293 #endif // QT_NO_PRINTER
15294  return success;
15295 }
15296 
15342 bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality, int resolution, QCP::ResolutionUnit resolutionUnit)
15343 {
15344  return saveRastered(fileName, width, height, scale, "PNG", quality, resolution, resolutionUnit);
15345 }
15346 
15389 bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality, int resolution, QCP::ResolutionUnit resolutionUnit)
15390 {
15391  return saveRastered(fileName, width, height, scale, "JPG", quality, resolution, resolutionUnit);
15392 }
15393 
15433 bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale, int resolution, QCP::ResolutionUnit resolutionUnit)
15434 {
15435  return saveRastered(fileName, width, height, scale, "BMP", -1, resolution, resolutionUnit);
15436 }
15437 
15447 {
15449 }
15450 
15457 {
15459 }
15460 
15466 void QCustomPlot::paintEvent(QPaintEvent *event)
15467 {
15468  Q_UNUSED(event)
15469  QCPPainter painter(this);
15470  if (painter.isActive())
15471  {
15472 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
15473  painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem
15474 #endif
15475  if (mBackgroundBrush.style() != Qt::NoBrush)
15476  painter.fillRect(mViewport, mBackgroundBrush);
15477  drawBackground(&painter);
15478  foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer, mPaintBuffers)
15479  buffer->draw(&painter);
15480  }
15481 }
15482 
15488 void QCustomPlot::resizeEvent(QResizeEvent *event)
15489 {
15490  Q_UNUSED(event)
15491  // resize and repaint the buffer:
15492  setViewport(rect());
15493  replot(rpQueuedRefresh); // queued refresh is important here, to prevent painting issues in some contexts (e.g. MDI subwindow)
15494 }
15495 
15505 void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event)
15506 {
15507  emit mouseDoubleClick(event);
15508  mMouseHasMoved = false;
15509  mMousePressPos = event->pos();
15510 
15511  // determine layerable under the cursor (this event is called instead of the second press event in a double-click):
15512  QList<QVariant> details;
15513  QList<QCPLayerable*> candidates = layerableListAt(mMousePressPos, false, &details);
15514  for (int i=0; i<candidates.size(); ++i)
15515  {
15516  event->accept(); // default impl of QCPLayerable's mouse events ignore the event, in that case propagate to next candidate in list
15517  candidates.at(i)->mouseDoubleClickEvent(event, details.at(i));
15518  if (event->isAccepted())
15519  {
15520  mMouseEventLayerable = candidates.at(i);
15521  mMouseEventLayerableDetails = details.at(i);
15522  break;
15523  }
15524  }
15525 
15526  // emit specialized object double click signals:
15527  if (!candidates.isEmpty())
15528  {
15529  if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(candidates.first()))
15530  {
15531  int dataIndex = 0;
15532  if (!details.first().value<QCPDataSelection>().isEmpty())
15533  dataIndex = details.first().value<QCPDataSelection>().dataRange().begin();
15534  emit plottableDoubleClick(ap, dataIndex, event);
15535  } else if (QCPAxis *ax = qobject_cast<QCPAxis*>(candidates.first()))
15536  emit axisDoubleClick(ax, details.first().value<QCPAxis::SelectablePart>(), event);
15537  else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(candidates.first()))
15538  emit itemDoubleClick(ai, event);
15539  else if (QCPLegend *lg = qobject_cast<QCPLegend*>(candidates.first()))
15540  emit legendDoubleClick(lg, nullptr, event);
15541  else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(candidates.first()))
15542  emit legendDoubleClick(li->parentLegend(), li, event);
15543  }
15544 
15545  event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event.
15546 }
15547 
15557 void QCustomPlot::mousePressEvent(QMouseEvent *event)
15558 {
15559  emit mousePress(event);
15560  // save some state to tell in releaseEvent whether it was a click:
15561  mMouseHasMoved = false;
15562  mMousePressPos = event->pos();
15563 
15565  {
15566  if (mSelectionRectMode != QCP::srmZoom || qobject_cast<QCPAxisRect*>(axisRectAt(mMousePressPos))) // in zoom mode only activate selection rect if on an axis rect
15568  } else
15569  {
15570  // no selection rect interaction, prepare for click signal emission and forward event to layerable under the cursor:
15571  QList<QVariant> details;
15572  QList<QCPLayerable*> candidates = layerableListAt(mMousePressPos, false, &details);
15573  if (!candidates.isEmpty())
15574  {
15575  mMouseSignalLayerable = candidates.first(); // candidate for signal emission is always topmost hit layerable (signal emitted in release event)
15576  mMouseSignalLayerableDetails = details.first();
15577  }
15578  // forward event to topmost candidate which accepts the event:
15579  for (int i=0; i<candidates.size(); ++i)
15580  {
15581  event->accept(); // default impl of QCPLayerable's mouse events call ignore() on the event, in that case propagate to next candidate in list
15582  candidates.at(i)->mousePressEvent(event, details.at(i));
15583  if (event->isAccepted())
15584  {
15585  mMouseEventLayerable = candidates.at(i);
15586  mMouseEventLayerableDetails = details.at(i);
15587  break;
15588  }
15589  }
15590  }
15591 
15592  event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event.
15593 }
15594 
15607 void QCustomPlot::mouseMoveEvent(QMouseEvent *event)
15608 {
15609  emit mouseMove(event);
15610 
15611  if (!mMouseHasMoved && (mMousePressPos-event->pos()).manhattanLength() > 3)
15612  mMouseHasMoved = true; // moved too far from mouse press position, don't handle as click on mouse release
15613 
15615  mSelectionRect->moveSelection(event);
15616  else if (mMouseEventLayerable) // call event of affected layerable:
15617  mMouseEventLayerable->mouseMoveEvent(event, mMousePressPos);
15618 
15619  event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event.
15620 }
15621 
15636 void QCustomPlot::mouseReleaseEvent(QMouseEvent *event)
15637 {
15638  emit mouseRelease(event);
15639 
15640  if (!mMouseHasMoved) // mouse hasn't moved (much) between press and release, so handle as click
15641  {
15642  if (mSelectionRect && mSelectionRect->isActive()) // a simple click shouldn't successfully finish a selection rect, so cancel it here
15644  if (event->button() == Qt::LeftButton)
15645  processPointSelection(event);
15646 
15647  // emit specialized click signals of QCustomPlot instance:
15648  if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable*>(mMouseSignalLayerable))
15649  {
15650  int dataIndex = 0;
15652  dataIndex = mMouseSignalLayerableDetails.value<QCPDataSelection>().dataRange().begin();
15653  emit plottableClick(ap, dataIndex, event);
15654  } else if (QCPAxis *ax = qobject_cast<QCPAxis*>(mMouseSignalLayerable))
15656  else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(mMouseSignalLayerable))
15657  emit itemClick(ai, event);
15658  else if (QCPLegend *lg = qobject_cast<QCPLegend*>(mMouseSignalLayerable))
15659  emit legendClick(lg, nullptr, event);
15660  else if (QCPAbstractLegendItem *li = qobject_cast<QCPAbstractLegendItem*>(mMouseSignalLayerable))
15661  emit legendClick(li->parentLegend(), li, event);
15662  mMouseSignalLayerable = nullptr;
15663  }
15664 
15665  if (mSelectionRect && mSelectionRect->isActive()) // Note: if a click was detected above, the selection rect is canceled there
15666  {
15667  // finish selection rect, the appropriate action will be taken via signal-slot connection:
15668  mSelectionRect->endSelection(event);
15669  } else
15670  {
15671  // call event of affected layerable:
15673  {
15674  mMouseEventLayerable->mouseReleaseEvent(event, mMousePressPos);
15675  mMouseEventLayerable = nullptr;
15676  }
15677  }
15678 
15679  if (noAntialiasingOnDrag())
15681 
15682  event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event.
15683 }
15684 
15690 void QCustomPlot::wheelEvent(QWheelEvent *event)
15691 {
15692  emit mouseWheel(event);
15693 
15694 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
15695  const QPointF pos = event->pos();
15696 #else
15697  const QPointF pos = event->position();
15698 #endif
15699 
15700  // forward event to layerable under cursor:
15701  foreach (QCPLayerable *candidate, layerableListAt(pos, false))
15702  {
15703  event->accept(); // default impl of QCPLayerable's mouse events ignore the event, in that case propagate to next candidate in list
15704  candidate->wheelEvent(event);
15705  if (event->isAccepted())
15706  break;
15707  }
15708  event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event.
15709 }
15710 
15722 {
15723  updateLayout();
15724 
15725  // draw viewport background pixmap:
15726  drawBackground(painter);
15727 
15728  // draw all layered objects (grid, axes, plottables, items, legend,...):
15729  foreach (QCPLayer *layer, mLayers)
15730  layer->draw(painter);
15731 
15732  /* Debug code to draw all layout element rects
15733  foreach (QCPLayoutElement *el, findChildren<QCPLayoutElement*>())
15734  {
15735  painter->setBrush(Qt::NoBrush);
15736  painter->setPen(QPen(QColor(0, 0, 0, 100), 0, Qt::DashLine));
15737  painter->drawRect(el->rect());
15738  painter->setPen(QPen(QColor(255, 0, 0, 100), 0, Qt::DashLine));
15739  painter->drawRect(el->outerRect());
15740  }
15741  */
15742 }
15743 
15753 {
15754  // run through layout phases:
15758 
15759  emit afterLayout();
15760 }
15761 
15780 {
15781  // Note: background color is handled in individual replot/save functions
15782 
15783  // draw background pixmap (on top of fill, if brush specified):
15784  if (!mBackgroundPixmap.isNull())
15785  {
15786  if (mBackgroundScaled)
15787  {
15788  // check whether mScaledBackground needs to be updated:
15789  QSize scaledSize(mBackgroundPixmap.size());
15790  scaledSize.scale(mViewport.size(), mBackgroundScaledMode);
15791  if (mScaledBackgroundPixmap.size() != scaledSize)
15792  mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
15793  painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect());
15794  } else
15795  {
15796  painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()));
15797  }
15798  }
15799 }
15800 
15821 {
15822  int bufferIndex = 0;
15823  if (mPaintBuffers.isEmpty())
15824  mPaintBuffers.append(QSharedPointer<QCPAbstractPaintBuffer>(createPaintBuffer()));
15825 
15826  for (int layerIndex = 0; layerIndex < mLayers.size(); ++layerIndex)
15827  {
15828  QCPLayer *layer = mLayers.at(layerIndex);
15829  if (layer->mode() == QCPLayer::lmLogical)
15830  {
15831  layer->mPaintBuffer = mPaintBuffers.at(bufferIndex).toWeakRef();
15832  } else if (layer->mode() == QCPLayer::lmBuffered)
15833  {
15834  ++bufferIndex;
15835  if (bufferIndex >= mPaintBuffers.size())
15836  mPaintBuffers.append(QSharedPointer<QCPAbstractPaintBuffer>(createPaintBuffer()));
15837  layer->mPaintBuffer = mPaintBuffers.at(bufferIndex).toWeakRef();
15838  if (layerIndex < mLayers.size()-1 && mLayers.at(layerIndex+1)->mode() == QCPLayer::lmLogical) // not last layer, and next one is logical, so prepare another buffer for next layerables
15839  {
15840  ++bufferIndex;
15841  if (bufferIndex >= mPaintBuffers.size())
15842  mPaintBuffers.append(QSharedPointer<QCPAbstractPaintBuffer>(createPaintBuffer()));
15843  }
15844  }
15845  }
15846  // remove unneeded buffers:
15847  while (mPaintBuffers.size()-1 > bufferIndex)
15848  mPaintBuffers.removeLast();
15849  // resize buffers to viewport size and clear contents:
15850  foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer, mPaintBuffers)
15851  {
15852  buffer->setSize(viewport().size()); // won't do anything if already correct size
15853  buffer->clear(Qt::transparent);
15854  buffer->setInvalidated();
15855  }
15856 }
15857 
15867 {
15868  if (mOpenGl)
15869  {
15870 #if defined(QCP_OPENGL_FBO)
15871  return new QCPPaintBufferGlFbo(viewport().size(), mBufferDevicePixelRatio, mGlContext, mGlPaintDevice);
15872 #elif defined(QCP_OPENGL_PBUFFER)
15873  return new QCPPaintBufferGlPbuffer(viewport().size(), mBufferDevicePixelRatio, mOpenGlMultisamples);
15874 #else
15875  qDebug() << Q_FUNC_INFO << "OpenGL enabled even though no support for it compiled in, this shouldn't have happened. Falling back to pixmap paint buffer.";
15877 #endif
15878  } else
15880 }
15881 
15894 {
15895  foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer, mPaintBuffers)
15896  {
15897  if (buffer->invalidated())
15898  return true;
15899  }
15900  return false;
15901 }
15902 
15917 {
15918 #ifdef QCP_OPENGL_FBO
15919  freeOpenGl();
15920  QSurfaceFormat proposedSurfaceFormat;
15921  proposedSurfaceFormat.setSamples(mOpenGlMultisamples);
15922 #ifdef QCP_OPENGL_OFFSCREENSURFACE
15923  QOffscreenSurface *surface = new QOffscreenSurface;
15924 #else
15925  QWindow *surface = new QWindow;
15926  surface->setSurfaceType(QSurface::OpenGLSurface);
15927 #endif
15928  surface->setFormat(proposedSurfaceFormat);
15929  surface->create();
15930  mGlSurface = QSharedPointer<QSurface>(surface);
15931  mGlContext = QSharedPointer<QOpenGLContext>(new QOpenGLContext);
15932  mGlContext->setFormat(mGlSurface->format());
15933  if (!mGlContext->create())
15934  {
15935  qDebug() << Q_FUNC_INFO << "Failed to create OpenGL context";
15936  mGlContext.clear();
15937  mGlSurface.clear();
15938  return false;
15939  }
15940  if (!mGlContext->makeCurrent(mGlSurface.data())) // context needs to be current to create paint device
15941  {
15942  qDebug() << Q_FUNC_INFO << "Failed to make opengl context current";
15943  mGlContext.clear();
15944  mGlSurface.clear();
15945  return false;
15946  }
15947  if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
15948  {
15949  qDebug() << Q_FUNC_INFO << "OpenGL of this system doesn't support frame buffer objects";
15950  mGlContext.clear();
15951  mGlSurface.clear();
15952  return false;
15953  }
15954  mGlPaintDevice = QSharedPointer<QOpenGLPaintDevice>(new QOpenGLPaintDevice);
15955  return true;
15956 #elif defined(QCP_OPENGL_PBUFFER)
15957  return QGLFormat::hasOpenGL();
15958 #else
15959  return false;
15960 #endif
15961 }
15962 
15975 {
15976 #ifdef QCP_OPENGL_FBO
15977  mGlPaintDevice.clear();
15978  mGlContext.clear();
15979  mGlSurface.clear();
15980 #endif
15981 }
15982 
15989 {
15990  if (xAxis == axis)
15991  xAxis = nullptr;
15992  if (xAxis2 == axis)
15993  xAxis2 = nullptr;
15994  if (yAxis == axis)
15995  yAxis = nullptr;
15996  if (yAxis2 == axis)
15997  yAxis2 = nullptr;
15998 
15999  // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers
16000 }
16001 
16008 {
16009  if (this->legend == legend)
16010  this->legend = nullptr;
16011 }
16012 
16030 void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event)
16031 {
16032  typedef QPair<QCPAbstractPlottable*, QCPDataSelection> SelectionCandidate;
16033  typedef QMultiMap<int, SelectionCandidate> SelectionCandidates; // map key is number of selected data points, so we have selections sorted by size
16034 
16035  bool selectionStateChanged = false;
16036 
16037  if (mInteractions.testFlag(QCP::iSelectPlottables))
16038  {
16039  SelectionCandidates potentialSelections;
16040  QRectF rectF(rect.normalized());
16041  if (QCPAxisRect *affectedAxisRect = axisRectAt(rectF.topLeft()))
16042  {
16043  // determine plottables that were hit by the rect and thus are candidates for selection:
16044  foreach (QCPAbstractPlottable *plottable, affectedAxisRect->plottables())
16045  {
16046  if (QCPPlottableInterface1D *plottableInterface = plottable->interface1D())
16047  {
16048  QCPDataSelection dataSel = plottableInterface->selectTestRect(rectF, true);
16049  if (!dataSel.isEmpty())
16050  potentialSelections.insert(dataSel.dataPointCount(), SelectionCandidate(plottable, dataSel));
16051  }
16052  }
16053 
16054  if (!mInteractions.testFlag(QCP::iMultiSelect))
16055  {
16056  // only leave plottable with most selected points in map, since we will only select a single plottable:
16057  if (!potentialSelections.isEmpty())
16058  {
16059  SelectionCandidates::iterator it = potentialSelections.begin();
16060  while (it != std::prev(potentialSelections.end())) // erase all except last element
16061  it = potentialSelections.erase(it);
16062  }
16063  }
16064 
16065  bool additive = event->modifiers().testFlag(mMultiSelectModifier);
16066  // deselect all other layerables if not additive selection:
16067  if (!additive)
16068  {
16069  // emit deselection except to those plottables who will be selected afterwards:
16070  foreach (QCPLayer *layer, mLayers)
16071  {
16072  foreach (QCPLayerable *layerable, layer->children())
16073  {
16074  if ((potentialSelections.isEmpty() || potentialSelections.constBegin()->first != layerable) && mInteractions.testFlag(layerable->selectionCategory()))
16075  {
16076  bool selChanged = false;
16077  layerable->deselectEvent(&selChanged);
16078  selectionStateChanged |= selChanged;
16079  }
16080  }
16081  }
16082  }
16083 
16084  // go through selections in reverse (largest selection first) and emit select events:
16085  SelectionCandidates::const_iterator it = potentialSelections.constEnd();
16086  while (it != potentialSelections.constBegin())
16087  {
16088  --it;
16089  if (mInteractions.testFlag(it.value().first->selectionCategory()))
16090  {
16091  bool selChanged = false;
16092  it.value().first->selectEvent(event, additive, QVariant::fromValue(it.value().second), &selChanged);
16093  selectionStateChanged |= selChanged;
16094  }
16095  }
16096  }
16097  }
16098 
16099  if (selectionStateChanged)
16100  {
16101  emit selectionChangedByUser();
16103  } else if (mSelectionRect)
16104  mSelectionRect->layer()->replot();
16105 }
16106 
16118 void QCustomPlot::processRectZoom(QRect rect, QMouseEvent *event)
16119 {
16120  Q_UNUSED(event)
16121  if (QCPAxisRect *axisRect = axisRectAt(rect.topLeft()))
16122  {
16123  QList<QCPAxis*> affectedAxes = QList<QCPAxis*>() << axisRect->rangeZoomAxes(Qt::Horizontal) << axisRect->rangeZoomAxes(Qt::Vertical);
16124  affectedAxes.removeAll(static_cast<QCPAxis*>(nullptr));
16125  axisRect->zoom(QRectF(rect), affectedAxes);
16126  }
16127  replot(rpQueuedReplot); // always replot to make selection rect disappear
16128 }
16129 
16147 void QCustomPlot::processPointSelection(QMouseEvent *event)
16148 {
16149  QVariant details;
16150  QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);
16151  bool selectionStateChanged = false;
16152  bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier);
16153  // deselect all other layerables if not additive selection:
16154  if (!additive)
16155  {
16156  foreach (QCPLayer *layer, mLayers)
16157  {
16158  foreach (QCPLayerable *layerable, layer->children())
16159  {
16160  if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory()))
16161  {
16162  bool selChanged = false;
16163  layerable->deselectEvent(&selChanged);
16164  selectionStateChanged |= selChanged;
16165  }
16166  }
16167  }
16168  }
16169  if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory()))
16170  {
16171  // a layerable was actually clicked, call its selectEvent:
16172  bool selChanged = false;
16173  clickedLayerable->selectEvent(event, additive, details, &selChanged);
16174  selectionStateChanged |= selChanged;
16175  }
16176  if (selectionStateChanged)
16177  {
16178  emit selectionChangedByUser();
16180  }
16181 }
16182 
16195 {
16196  if (mPlottables.contains(plottable))
16197  {
16198  qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast<quintptr>(plottable);
16199  return false;
16200  }
16201  if (plottable->parentPlot() != this)
16202  {
16203  qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(plottable);
16204  return false;
16205  }
16206 
16207  mPlottables.append(plottable);
16208  // possibly add plottable to legend:
16211  if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor)
16213  return true;
16214 }
16215 
16226 {
16227  if (!graph)
16228  {
16229  qDebug() << Q_FUNC_INFO << "passed graph is zero";
16230  return false;
16231  }
16232  if (mGraphs.contains(graph))
16233  {
16234  qDebug() << Q_FUNC_INFO << "graph already registered with this QCustomPlot";
16235  return false;
16236  }
16237 
16238  mGraphs.append(graph);
16239  return true;
16240 }
16241 
16242 
16253 {
16254  if (mItems.contains(item))
16255  {
16256  qDebug() << Q_FUNC_INFO << "item already added to this QCustomPlot:" << reinterpret_cast<quintptr>(item);
16257  return false;
16258  }
16259  if (item->parentPlot() != this)
16260  {
16261  qDebug() << Q_FUNC_INFO << "item not created with this QCustomPlot as parent:" << reinterpret_cast<quintptr>(item);
16262  return false;
16263  }
16264 
16265  mItems.append(item);
16266  if (!item->layer()) // usually the layer is already set in the constructor of the item (via QCPLayerable constructor)
16268  return true;
16269 }
16270 
16278 {
16279  for (int i=0; i<mLayers.size(); ++i)
16280  mLayers.at(i)->mIndex = i;
16281 }
16282 
16298 QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const
16299 {
16300  QList<QVariant> details;
16301  QList<QCPLayerable*> candidates = layerableListAt(pos, onlySelectable, selectionDetails ? &details : nullptr);
16302  if (selectionDetails && !details.isEmpty())
16303  *selectionDetails = details.first();
16304  if (!candidates.isEmpty())
16305  return candidates.first();
16306  else
16307  return nullptr;
16308 }
16309 
16329 QList<QCPLayerable*> QCustomPlot::layerableListAt(const QPointF &pos, bool onlySelectable, QList<QVariant> *selectionDetails) const
16330 {
16331  QList<QCPLayerable*> result;
16332  for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex)
16333  {
16334  const QList<QCPLayerable*> layerables = mLayers.at(layerIndex)->children();
16335  for (int i=layerables.size()-1; i>=0; --i)
16336  {
16337  if (!layerables.at(i)->realVisibility())
16338  continue;
16339  QVariant details;
16340  double dist = layerables.at(i)->selectTest(pos, onlySelectable, selectionDetails ? &details : nullptr);
16341  if (dist >= 0 && dist < selectionTolerance())
16342  {
16343  result.append(layerables.at(i));
16344  if (selectionDetails)
16345  selectionDetails->append(details);
16346  }
16347  }
16348  }
16349  return result;
16350 }
16351 
16370 bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality, int resolution, QCP::ResolutionUnit resolutionUnit)
16371 {
16372  QImage buffer = toPixmap(width, height, scale).toImage();
16373 
16374  int dotsPerMeter = 0;
16375  switch (resolutionUnit)
16376  {
16377  case QCP::ruDotsPerMeter: dotsPerMeter = resolution; break;
16378  case QCP::ruDotsPerCentimeter: dotsPerMeter = resolution*100; break;
16379  case QCP::ruDotsPerInch: dotsPerMeter = int(resolution/0.0254); break;
16380  }
16381  buffer.setDotsPerMeterX(dotsPerMeter); // this is saved together with some image formats, e.g. PNG, and is relevant when opening image in other tools
16382  buffer.setDotsPerMeterY(dotsPerMeter); // this is saved together with some image formats, e.g. PNG, and is relevant when opening image in other tools
16383  if (!buffer.isNull())
16384  return buffer.save(fileName, format, quality);
16385  else
16386  return false;
16387 }
16388 
16397 QPixmap QCustomPlot::toPixmap(int width, int height, double scale)
16398 {
16399  // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too.
16400  int newWidth, newHeight;
16401  if (width == 0 || height == 0)
16402  {
16403  newWidth = this->width();
16404  newHeight = this->height();
16405  } else
16406  {
16407  newWidth = width;
16408  newHeight = height;
16409  }
16410  int scaledWidth = qRound(scale*newWidth);
16411  int scaledHeight = qRound(scale*newHeight);
16412 
16413  QPixmap result(scaledWidth, scaledHeight);
16414  result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later
16415  QCPPainter painter;
16416  painter.begin(&result);
16417  if (painter.isActive())
16418  {
16419  QRect oldViewport = viewport();
16420  setViewport(QRect(0, 0, newWidth, newHeight));
16422  if (!qFuzzyCompare(scale, 1.0))
16423  {
16424  if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales
16426  painter.scale(scale, scale);
16427  }
16428  if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) // solid fills were done a few lines above with QPixmap::fill
16429  painter.fillRect(mViewport, mBackgroundBrush);
16430  draw(&painter);
16431  setViewport(oldViewport);
16432  painter.end();
16433  } else // might happen if pixmap has width or height zero
16434  {
16435  qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap";
16436  return QPixmap();
16437  }
16438  return result;
16439 }
16440 
16453 void QCustomPlot::toPainter(QCPPainter *painter, int width, int height)
16454 {
16455  // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too.
16456  int newWidth, newHeight;
16457  if (width == 0 || height == 0)
16458  {
16459  newWidth = this->width();
16460  newHeight = this->height();
16461  } else
16462  {
16463  newWidth = width;
16464  newHeight = height;
16465  }
16466 
16467  if (painter->isActive())
16468  {
16469  QRect oldViewport = viewport();
16470  setViewport(QRect(0, 0, newWidth, newHeight));
16471  painter->setMode(QCPPainter::pmNoCaching);
16472  if (mBackgroundBrush.style() != Qt::NoBrush) // unlike in toPixmap, we can't do QPixmap::fill for Qt::SolidPattern brush style, so we also draw solid fills with fillRect here
16473  painter->fillRect(mViewport, mBackgroundBrush);
16474  draw(painter);
16475  setViewport(oldViewport);
16476  } else
16477  qDebug() << Q_FUNC_INFO << "Passed painter is not active";
16478 }
16479 /* end of 'src/core.cpp' */
16480 
16481 
16482 /* including file 'src/colorgradient.cpp' */
16483 /* modified 2021-03-29T02:30:44, size 25278 */
16484 
16485 
16489 
16527  mLevelCount(350),
16528  mColorInterpolation(ciRGB),
16529  mNanHandling(nhNone),
16530  mNanColor(Qt::black),
16531  mPeriodic(false),
16532  mColorBufferInvalidated(true)
16533 {
16534  mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount);
16535 }
16536 
16544  mLevelCount(350),
16545  mColorInterpolation(ciRGB),
16546  mNanHandling(nhNone),
16547  mNanColor(Qt::black),
16548  mPeriodic(false),
16549  mColorBufferInvalidated(true)
16550 {
16551  mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount);
16552  loadPreset(preset);
16553 }
16554 
16555 /* undocumented operator */
16557 {
16558  return ((other.mLevelCount == this->mLevelCount) &&
16559  (other.mColorInterpolation == this->mColorInterpolation) &&
16560  (other.mNanHandling == this ->mNanHandling) &&
16561  (other.mNanColor == this->mNanColor) &&
16562  (other.mPeriodic == this->mPeriodic) &&
16563  (other.mColorStops == this->mColorStops));
16564 }
16565 
16573 {
16574  if (n < 2)
16575  {
16576  qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n;
16577  n = 2;
16578  }
16579  if (n != mLevelCount)
16580  {
16581  mLevelCount = n;
16582  mColorBufferInvalidated = true;
16583  }
16584 }
16585 
16597 void QCPColorGradient::setColorStops(const QMap<double, QColor> &colorStops)
16598 {
16600  mColorBufferInvalidated = true;
16601 }
16602 
16609 void QCPColorGradient::setColorStopAt(double position, const QColor &color)
16610 {
16611  mColorStops.insert(position, color);
16612  mColorBufferInvalidated = true;
16613 }
16614 
16623 {
16624  if (interpolation != mColorInterpolation)
16625  {
16626  mColorInterpolation = interpolation;
16627  mColorBufferInvalidated = true;
16628  }
16629 }
16630 
16637 {
16638  mNanHandling = handling;
16639 }
16640 
16648 {
16649  mNanColor = color;
16650 }
16651 
16668 {
16669  mPeriodic = enabled;
16670 }
16671 
16690 void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic)
16691 {
16692  // If you change something here, make sure to also adapt color() and the other colorize() overload
16693  if (!data)
16694  {
16695  qDebug() << Q_FUNC_INFO << "null pointer given as data";
16696  return;
16697  }
16698  if (!scanLine)
16699  {
16700  qDebug() << Q_FUNC_INFO << "null pointer given as scanLine";
16701  return;
16702  }
16705 
16706  const bool skipNanCheck = mNanHandling == nhNone;
16707  const double posToIndexFactor = !logarithmic ? (mLevelCount-1)/range.size() : (mLevelCount-1)/qLn(range.upper/range.lower);
16708  for (int i=0; i<n; ++i)
16709  {
16710  const double value = data[dataIndexFactor*i];
16711  if (skipNanCheck || !std::isnan(value))
16712  {
16713  int index = int((!logarithmic ? value-range.lower : qLn(value/range.lower)) * posToIndexFactor);
16714  if (!mPeriodic)
16715  {
16716  index = qBound(0, index, mLevelCount-1);
16717  } else
16718  {
16719  index %= mLevelCount;
16720  if (index < 0)
16721  index += mLevelCount;
16722  }
16723  scanLine[i] = mColorBuffer.at(index);
16724  } else
16725  {
16726  switch(mNanHandling)
16727  {
16728  case nhLowestColor: scanLine[i] = mColorBuffer.first(); break;
16729  case nhHighestColor: scanLine[i] = mColorBuffer.last(); break;
16730  case nhTransparent: scanLine[i] = qRgba(0, 0, 0, 0); break;
16731  case nhNanColor: scanLine[i] = mNanColor.rgba(); break;
16732  case nhNone: break; // shouldn't happen
16733  }
16734  }
16735  }
16736 }
16737 
16746 void QCPColorGradient::colorize(const double *data, const unsigned char *alpha, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic)
16747 {
16748  // If you change something here, make sure to also adapt color() and the other colorize() overload
16749  if (!data)
16750  {
16751  qDebug() << Q_FUNC_INFO << "null pointer given as data";
16752  return;
16753  }
16754  if (!alpha)
16755  {
16756  qDebug() << Q_FUNC_INFO << "null pointer given as alpha";
16757  return;
16758  }
16759  if (!scanLine)
16760  {
16761  qDebug() << Q_FUNC_INFO << "null pointer given as scanLine";
16762  return;
16763  }
16766 
16767  const bool skipNanCheck = mNanHandling == nhNone;
16768  const double posToIndexFactor = !logarithmic ? (mLevelCount-1)/range.size() : (mLevelCount-1)/qLn(range.upper/range.lower);
16769  for (int i=0; i<n; ++i)
16770  {
16771  const double value = data[dataIndexFactor*i];
16772  if (skipNanCheck || !std::isnan(value))
16773  {
16774  int index = int((!logarithmic ? value-range.lower : qLn(value/range.lower)) * posToIndexFactor);
16775  if (!mPeriodic)
16776  {
16777  index = qBound(0, index, mLevelCount-1);
16778  } else
16779  {
16780  index %= mLevelCount;
16781  if (index < 0)
16782  index += mLevelCount;
16783  }
16784  if (alpha[dataIndexFactor*i] == 255)
16785  {
16786  scanLine[i] = mColorBuffer.at(index);
16787  } else
16788  {
16789  const QRgb rgb = mColorBuffer.at(index);
16790  const float alphaF = alpha[dataIndexFactor*i]/255.0f;
16791  scanLine[i] = qRgba(int(qRed(rgb)*alphaF), int(qGreen(rgb)*alphaF), int(qBlue(rgb)*alphaF), int(qAlpha(rgb)*alphaF)); // also multiply r,g,b with alpha, to conform to Format_ARGB32_Premultiplied
16792  }
16793  } else
16794  {
16795  switch(mNanHandling)
16796  {
16797  case nhLowestColor: scanLine[i] = mColorBuffer.first(); break;
16798  case nhHighestColor: scanLine[i] = mColorBuffer.last(); break;
16799  case nhTransparent: scanLine[i] = qRgba(0, 0, 0, 0); break;
16800  case nhNanColor: scanLine[i] = mNanColor.rgba(); break;
16801  case nhNone: break; // shouldn't happen
16802  }
16803  }
16804  }
16805 }
16806 
16819 QRgb QCPColorGradient::color(double position, const QCPRange &range, bool logarithmic)
16820 {
16821  // If you change something here, make sure to also adapt ::colorize()
16824 
16825  const bool skipNanCheck = mNanHandling == nhNone;
16826  if (!skipNanCheck && std::isnan(position))
16827  {
16828  switch(mNanHandling)
16829  {
16830  case nhLowestColor: return mColorBuffer.first();
16831  case nhHighestColor: return mColorBuffer.last();
16832  case nhTransparent: return qRgba(0, 0, 0, 0);
16833  case nhNanColor: return mNanColor.rgba();
16834  case nhNone: return qRgba(0, 0, 0, 0); // shouldn't happen
16835  }
16836  }
16837 
16838  const double posToIndexFactor = !logarithmic ? (mLevelCount-1)/range.size() : (mLevelCount-1)/qLn(range.upper/range.lower);
16839  int index = int((!logarithmic ? position-range.lower : qLn(position/range.lower)) * posToIndexFactor);
16840  if (!mPeriodic)
16841  {
16842  index = qBound(0, index, mLevelCount-1);
16843  } else
16844  {
16845  index %= mLevelCount;
16846  if (index < 0)
16847  index += mLevelCount;
16848  }
16849  return mColorBuffer.at(index);
16850 }
16851 
16860 {
16861  clearColorStops();
16862  switch (preset)
16863  {
16864  case gpGrayscale:
16866  setColorStopAt(0, Qt::black);
16867  setColorStopAt(1, Qt::white);
16868  break;
16869  case gpHot:
16871  setColorStopAt(0, QColor(50, 0, 0));
16872  setColorStopAt(0.2, QColor(180, 10, 0));
16873  setColorStopAt(0.4, QColor(245, 50, 0));
16874  setColorStopAt(0.6, QColor(255, 150, 10));
16875  setColorStopAt(0.8, QColor(255, 255, 50));
16876  setColorStopAt(1, QColor(255, 255, 255));
16877  break;
16878  case gpCold:
16880  setColorStopAt(0, QColor(0, 0, 50));
16881  setColorStopAt(0.2, QColor(0, 10, 180));
16882  setColorStopAt(0.4, QColor(0, 50, 245));
16883  setColorStopAt(0.6, QColor(10, 150, 255));
16884  setColorStopAt(0.8, QColor(50, 255, 255));
16885  setColorStopAt(1, QColor(255, 255, 255));
16886  break;
16887  case gpNight:
16889  setColorStopAt(0, QColor(10, 20, 30));
16890  setColorStopAt(1, QColor(250, 255, 250));
16891  break;
16892  case gpCandy:
16894  setColorStopAt(0, QColor(0, 0, 255));
16895  setColorStopAt(1, QColor(255, 250, 250));
16896  break;
16897  case gpGeography:
16899  setColorStopAt(0, QColor(70, 170, 210));
16900  setColorStopAt(0.20, QColor(90, 160, 180));
16901  setColorStopAt(0.25, QColor(45, 130, 175));
16902  setColorStopAt(0.30, QColor(100, 140, 125));
16903  setColorStopAt(0.5, QColor(100, 140, 100));
16904  setColorStopAt(0.6, QColor(130, 145, 120));
16905  setColorStopAt(0.7, QColor(140, 130, 120));
16906  setColorStopAt(0.9, QColor(180, 190, 190));
16907  setColorStopAt(1, QColor(210, 210, 230));
16908  break;
16909  case gpIon:
16911  setColorStopAt(0, QColor(50, 10, 10));
16912  setColorStopAt(0.45, QColor(0, 0, 255));
16913  setColorStopAt(0.8, QColor(0, 255, 255));
16914  setColorStopAt(1, QColor(0, 255, 0));
16915  break;
16916  case gpThermal:
16918  setColorStopAt(0, QColor(0, 0, 50));
16919  setColorStopAt(0.15, QColor(20, 0, 120));
16920  setColorStopAt(0.33, QColor(200, 30, 140));
16921  setColorStopAt(0.6, QColor(255, 100, 0));
16922  setColorStopAt(0.85, QColor(255, 255, 40));
16923  setColorStopAt(1, QColor(255, 255, 255));
16924  break;
16925  case gpPolar:
16927  setColorStopAt(0, QColor(50, 255, 255));
16928  setColorStopAt(0.18, QColor(10, 70, 255));
16929  setColorStopAt(0.28, QColor(10, 10, 190));
16930  setColorStopAt(0.5, QColor(0, 0, 0));
16931  setColorStopAt(0.72, QColor(190, 10, 10));
16932  setColorStopAt(0.82, QColor(255, 70, 10));
16933  setColorStopAt(1, QColor(255, 255, 50));
16934  break;
16935  case gpSpectrum:
16937  setColorStopAt(0, QColor(50, 0, 50));
16938  setColorStopAt(0.15, QColor(0, 0, 255));
16939  setColorStopAt(0.35, QColor(0, 255, 255));
16940  setColorStopAt(0.6, QColor(255, 255, 0));
16941  setColorStopAt(0.75, QColor(255, 30, 0));
16942  setColorStopAt(1, QColor(50, 0, 0));
16943  break;
16944  case gpJet:
16946  setColorStopAt(0, QColor(0, 0, 100));
16947  setColorStopAt(0.15, QColor(0, 50, 255));
16948  setColorStopAt(0.35, QColor(0, 255, 255));
16949  setColorStopAt(0.65, QColor(255, 255, 0));
16950  setColorStopAt(0.85, QColor(255, 30, 0));
16951  setColorStopAt(1, QColor(100, 0, 0));
16952  break;
16953  case gpHues:
16955  setColorStopAt(0, QColor(255, 0, 0));
16956  setColorStopAt(1.0/3.0, QColor(0, 0, 255));
16957  setColorStopAt(2.0/3.0, QColor(0, 255, 0));
16958  setColorStopAt(1, QColor(255, 0, 0));
16959  break;
16960  }
16961 }
16962 
16969 {
16970  mColorStops.clear();
16971  mColorBufferInvalidated = true;
16972 }
16973 
16981 {
16982  QCPColorGradient result(*this);
16983  result.clearColorStops();
16984  for (QMap<double, QColor>::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it)
16985  result.setColorStopAt(1.0-it.key(), it.value());
16986  return result;
16987 }
16988 
16995 {
16996  for (QMap<double, QColor>::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it)
16997  {
16998  if (it.value().alpha() < 255)
16999  return true;
17000  }
17001  return false;
17002 }
17003 
17010 {
17011  if (mColorBuffer.size() != mLevelCount)
17012  mColorBuffer.resize(mLevelCount);
17013  if (mColorStops.size() > 1)
17014  {
17015  double indexToPosFactor = 1.0/double(mLevelCount-1);
17016  const bool useAlpha = stopsUseAlpha();
17017  for (int i=0; i<mLevelCount; ++i)
17018  {
17019  double position = i*indexToPosFactor;
17020  QMap<double, QColor>::const_iterator it = mColorStops.lowerBound(position);
17021  if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop
17022  {
17023  if (useAlpha)
17024  {
17025  const QColor col = std::prev(it).value();
17026  const double alphaPremultiplier = col.alpha()/255.0; // since we use QImage::Format_ARGB32_Premultiplied
17027  mColorBuffer[i] = qRgba(int(col.red()*alphaPremultiplier),
17028  int(col.green()*alphaPremultiplier),
17029  int(col.blue()*alphaPremultiplier),
17030  col.alpha());
17031  } else
17032  mColorBuffer[i] = std::prev(it).value().rgba();
17033  } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop
17034  {
17035  if (useAlpha)
17036  {
17037  const QColor &col = it.value();
17038  const double alphaPremultiplier = col.alpha()/255.0; // since we use QImage::Format_ARGB32_Premultiplied
17039  mColorBuffer[i] = qRgba(int(col.red()*alphaPremultiplier),
17040  int(col.green()*alphaPremultiplier),
17041  int(col.blue()*alphaPremultiplier),
17042  col.alpha());
17043  } else
17044  mColorBuffer[i] = it.value().rgba();
17045  } else // position is in between stops (or on an intermediate stop), interpolate color
17046  {
17047  QMap<double, QColor>::const_iterator high = it;
17048  QMap<double, QColor>::const_iterator low = std::prev(it);
17049  double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1
17050  switch (mColorInterpolation)
17051  {
17052  case ciRGB:
17053  {
17054  if (useAlpha)
17055  {
17056  const int alpha = int((1-t)*low.value().alpha() + t*high.value().alpha());
17057  const double alphaPremultiplier = alpha/255.0; // since we use QImage::Format_ARGB32_Premultiplied
17058  mColorBuffer[i] = qRgba(int( ((1-t)*low.value().red() + t*high.value().red())*alphaPremultiplier ),
17059  int( ((1-t)*low.value().green() + t*high.value().green())*alphaPremultiplier ),
17060  int( ((1-t)*low.value().blue() + t*high.value().blue())*alphaPremultiplier ),
17061  alpha);
17062  } else
17063  {
17064  mColorBuffer[i] = qRgb(int( ((1-t)*low.value().red() + t*high.value().red()) ),
17065  int( ((1-t)*low.value().green() + t*high.value().green()) ),
17066  int( ((1-t)*low.value().blue() + t*high.value().blue())) );
17067  }
17068  break;
17069  }
17070  case ciHSV:
17071  {
17072  QColor lowHsv = low.value().toHsv();
17073  QColor highHsv = high.value().toHsv();
17074  double hue = 0;
17075  double hueDiff = highHsv.hueF()-lowHsv.hueF();
17076  if (hueDiff > 0.5)
17077  hue = lowHsv.hueF() - t*(1.0-hueDiff);
17078  else if (hueDiff < -0.5)
17079  hue = lowHsv.hueF() + t*(1.0+hueDiff);
17080  else
17081  hue = lowHsv.hueF() + t*hueDiff;
17082  if (hue < 0) hue += 1.0;
17083  else if (hue >= 1.0) hue -= 1.0;
17084  if (useAlpha)
17085  {
17086  const QRgb rgb = QColor::fromHsvF(hue,
17087  (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(),
17088  (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
17089  const double alpha = (1-t)*lowHsv.alphaF() + t*highHsv.alphaF();
17090  mColorBuffer[i] = qRgba(int(qRed(rgb)*alpha), int(qGreen(rgb)*alpha), int(qBlue(rgb)*alpha), int(255*alpha));
17091  }
17092  else
17093  {
17094  mColorBuffer[i] = QColor::fromHsvF(hue,
17095  (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(),
17096  (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
17097  }
17098  break;
17099  }
17100  }
17101  }
17102  }
17103  } else if (mColorStops.size() == 1)
17104  {
17105  const QRgb rgb = mColorStops.constBegin().value().rgb();
17106  const double alpha = mColorStops.constBegin().value().alphaF();
17107  mColorBuffer.fill(qRgba(int(qRed(rgb)*alpha), int(qGreen(rgb)*alpha), int(qBlue(rgb)*alpha), int(255*alpha)));
17108  } else // mColorStops is empty, fill color buffer with black
17109  {
17110  mColorBuffer.fill(qRgb(0, 0, 0));
17111  }
17112  mColorBufferInvalidated = false;
17113 }
17114 /* end of 'src/colorgradient.cpp' */
17115 
17116 
17117 /* including file 'src/selectiondecorator-bracket.cpp' */
17118 /* modified 2021-03-29T02:30:44, size 12308 */
17119 
17123 
17144  mBracketPen(QPen(Qt::black)),
17145  mBracketBrush(Qt::NoBrush),
17146  mBracketWidth(5),
17147  mBracketHeight(50),
17148  mBracketStyle(bsSquareBracket),
17149  mTangentToData(false),
17150  mTangentAverage(2)
17151 {
17152 
17153 }
17154 
17156 {
17157 }
17158 
17164 {
17165  mBracketPen = pen;
17166 }
17167 
17173 {
17174  mBracketBrush = brush;
17175 }
17176 
17183 {
17184  mBracketWidth = width;
17185 }
17186 
17193 {
17194  mBracketHeight = height;
17195 }
17196 
17203 {
17204  mBracketStyle = style;
17205 }
17206 
17215 {
17216  mTangentToData = enabled;
17217 }
17218 
17228 {
17229  mTangentAverage = pointCount;
17230  if (mTangentAverage < 1)
17231  mTangentAverage = 1;
17232 }
17233 
17247 void QCPSelectionDecoratorBracket::drawBracket(QCPPainter *painter, int direction) const
17248 {
17249  switch (mBracketStyle)
17250  {
17251  case bsSquareBracket:
17252  {
17253  painter->drawLine(QLineF(mBracketWidth*direction, -mBracketHeight*0.5, 0, -mBracketHeight*0.5));
17254  painter->drawLine(QLineF(mBracketWidth*direction, mBracketHeight*0.5, 0, mBracketHeight*0.5));
17255  painter->drawLine(QLineF(0, -mBracketHeight*0.5, 0, mBracketHeight*0.5));
17256  break;
17257  }
17258  case bsHalfEllipse:
17259  {
17260  painter->drawArc(QRectF(-mBracketWidth*0.5, -mBracketHeight*0.5, mBracketWidth, mBracketHeight), -90*16, -180*16*direction);
17261  break;
17262  }
17263  case bsEllipse:
17264  {
17265  painter->drawEllipse(QRectF(-mBracketWidth*0.5, -mBracketHeight*0.5, mBracketWidth, mBracketHeight));
17266  break;
17267  }
17268  case bsPlus:
17269  {
17270  painter->drawLine(QLineF(0, -mBracketHeight*0.5, 0, mBracketHeight*0.5));
17271  painter->drawLine(QLineF(-mBracketWidth*0.5, 0, mBracketWidth*0.5, 0));
17272  break;
17273  }
17274  default:
17275  {
17276  qDebug() << Q_FUNC_INFO << "unknown/custom bracket style can't be handeld by default implementation:" << static_cast<int>(mBracketStyle);
17277  break;
17278  }
17279  }
17280 }
17281 
17291 {
17292  if (!mPlottable || selection.isEmpty()) return;
17293 
17294  if (QCPPlottableInterface1D *interface1d = mPlottable->interface1D())
17295  {
17296  foreach (const QCPDataRange &dataRange, selection.dataRanges())
17297  {
17298  // determine position and (if tangent mode is enabled) angle of brackets:
17299  int openBracketDir = (mPlottable->keyAxis() && !mPlottable->keyAxis()->rangeReversed()) ? 1 : -1;
17300  int closeBracketDir = -openBracketDir;
17301  QPointF openBracketPos = getPixelCoordinates(interface1d, dataRange.begin());
17302  QPointF closeBracketPos = getPixelCoordinates(interface1d, dataRange.end()-1);
17303  double openBracketAngle = 0;
17304  double closeBracketAngle = 0;
17305  if (mTangentToData)
17306  {
17307  openBracketAngle = getTangentAngle(interface1d, dataRange.begin(), openBracketDir);
17308  closeBracketAngle = getTangentAngle(interface1d, dataRange.end()-1, closeBracketDir);
17309  }
17310  // draw opening bracket:
17311  QTransform oldTransform = painter->transform();
17312  painter->setPen(mBracketPen);
17313  painter->setBrush(mBracketBrush);
17314  painter->translate(openBracketPos);
17315  painter->rotate(openBracketAngle/M_PI*180.0);
17316  drawBracket(painter, openBracketDir);
17317  painter->setTransform(oldTransform);
17318  // draw closing bracket:
17319  painter->setPen(mBracketPen);
17320  painter->setBrush(mBracketBrush);
17321  painter->translate(closeBracketPos);
17322  painter->rotate(closeBracketAngle/M_PI*180.0);
17323  drawBracket(painter, closeBracketDir);
17324  painter->setTransform(oldTransform);
17325  }
17326  }
17327 }
17328 
17342 double QCPSelectionDecoratorBracket::getTangentAngle(const QCPPlottableInterface1D *interface1d, int dataIndex, int direction) const
17343 {
17344  if (!interface1d || dataIndex < 0 || dataIndex >= interface1d->dataCount())
17345  return 0;
17346  direction = direction < 0 ? -1 : 1; // enforce direction is either -1 or 1
17347 
17348  // how many steps we can actually go from index in the given direction without exceeding data bounds:
17349  int averageCount;
17350  if (direction < 0)
17351  averageCount = qMin(mTangentAverage, dataIndex);
17352  else
17353  averageCount = qMin(mTangentAverage, interface1d->dataCount()-1-dataIndex);
17354  qDebug() << averageCount;
17355  // calculate point average of averageCount points:
17356  QVector<QPointF> points(averageCount);
17357  QPointF pointsAverage;
17358  int currentIndex = dataIndex;
17359  for (int i=0; i<averageCount; ++i)
17360  {
17361  points[i] = getPixelCoordinates(interface1d, currentIndex);
17362  pointsAverage += points[i];
17363  currentIndex += direction;
17364  }
17365  pointsAverage /= double(averageCount);
17366 
17367  // calculate slope of linear regression through points:
17368  double numSum = 0;
17369  double denomSum = 0;
17370  for (int i=0; i<averageCount; ++i)
17371  {
17372  const double dx = points.at(i).x()-pointsAverage.x();
17373  const double dy = points.at(i).y()-pointsAverage.y();
17374  numSum += dx*dy;
17375  denomSum += dx*dx;
17376  }
17377  if (!qFuzzyIsNull(denomSum) && !qFuzzyIsNull(numSum))
17378  {
17379  return qAtan2(numSum, denomSum);
17380  } else // undetermined angle, probably mTangentAverage == 1, so using only one data point
17381  return 0;
17382 }
17383 
17389 QPointF QCPSelectionDecoratorBracket::getPixelCoordinates(const QCPPlottableInterface1D *interface1d, int dataIndex) const
17390 {
17391  QCPAxis *keyAxis = mPlottable->keyAxis();
17392  QCPAxis *valueAxis = mPlottable->valueAxis();
17393  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {0, 0}; }
17394 
17395  if (keyAxis->orientation() == Qt::Horizontal)
17396  return {keyAxis->coordToPixel(interface1d->dataMainKey(dataIndex)), valueAxis->coordToPixel(interface1d->dataMainValue(dataIndex))};
17397  else
17398  return {valueAxis->coordToPixel(interface1d->dataMainValue(dataIndex)), keyAxis->coordToPixel(interface1d->dataMainKey(dataIndex))};
17399 }
17400 /* end of 'src/selectiondecorator-bracket.cpp' */
17401 
17402 
17403 /* including file 'src/layoutelements/layoutelement-axisrect.cpp' */
17404 /* modified 2021-03-29T02:30:44, size 47193 */
17405 
17406 
17410 
17448 /* start documentation of inline functions */
17449 
17530 /* end documentation of inline functions */
17531 
17536 QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) :
17537  QCPLayoutElement(parentPlot),
17538  mBackgroundBrush(Qt::NoBrush),
17539  mBackgroundScaled(true),
17540  mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
17541  mInsetLayout(new QCPLayoutInset),
17542  mRangeDrag(Qt::Horizontal|Qt::Vertical),
17543  mRangeZoom(Qt::Horizontal|Qt::Vertical),
17544  mRangeZoomFactorHorz(0.85),
17545  mRangeZoomFactorVert(0.85),
17546  mDragging(false)
17547 {
17550  mInsetLayout->setParent(this);
17551 
17552  setMinimumSize(50, 50);
17553  setMinimumMargins(QMargins(15, 15, 15, 15));
17554  mAxes.insert(QCPAxis::atLeft, QList<QCPAxis*>());
17555  mAxes.insert(QCPAxis::atRight, QList<QCPAxis*>());
17556  mAxes.insert(QCPAxis::atTop, QList<QCPAxis*>());
17557  mAxes.insert(QCPAxis::atBottom, QList<QCPAxis*>());
17558 
17559  if (setupDefaultAxes)
17560  {
17561  QCPAxis *xAxis = addAxis(QCPAxis::atBottom);
17562  QCPAxis *yAxis = addAxis(QCPAxis::atLeft);
17563  QCPAxis *xAxis2 = addAxis(QCPAxis::atTop);
17564  QCPAxis *yAxis2 = addAxis(QCPAxis::atRight);
17565  setRangeDragAxes(xAxis, yAxis);
17566  setRangeZoomAxes(xAxis, yAxis);
17567  xAxis2->setVisible(false);
17568  yAxis2->setVisible(false);
17569  xAxis->grid()->setVisible(true);
17570  yAxis->grid()->setVisible(true);
17571  xAxis2->grid()->setVisible(false);
17572  yAxis2->grid()->setVisible(false);
17573  xAxis2->grid()->setZeroLinePen(Qt::NoPen);
17574  yAxis2->grid()->setZeroLinePen(Qt::NoPen);
17575  xAxis2->grid()->setVisible(false);
17576  yAxis2->grid()->setVisible(false);
17577  }
17578 }
17579 
17581 {
17582  delete mInsetLayout;
17583  mInsetLayout = nullptr;
17584 
17585  foreach (QCPAxis *axis, axes())
17586  removeAxis(axis);
17587 }
17588 
17595 {
17596  return mAxes.value(type).size();
17597 }
17598 
17605 {
17606  QList<QCPAxis*> ax(mAxes.value(type));
17607  if (index >= 0 && index < ax.size())
17608  {
17609  return ax.at(index);
17610  } else
17611  {
17612  qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index;
17613  return nullptr;
17614  }
17615 }
17616 
17625 QList<QCPAxis*> QCPAxisRect::axes(QCPAxis::AxisTypes types) const
17626 {
17627  QList<QCPAxis*> result;
17628  if (types.testFlag(QCPAxis::atLeft))
17629  result << mAxes.value(QCPAxis::atLeft);
17630  if (types.testFlag(QCPAxis::atRight))
17631  result << mAxes.value(QCPAxis::atRight);
17632  if (types.testFlag(QCPAxis::atTop))
17633  result << mAxes.value(QCPAxis::atTop);
17634  if (types.testFlag(QCPAxis::atBottom))
17635  result << mAxes.value(QCPAxis::atBottom);
17636  return result;
17637 }
17638 
17643 QList<QCPAxis*> QCPAxisRect::axes() const
17644 {
17645  QList<QCPAxis*> result;
17646  QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
17647  while (it.hasNext())
17648  {
17649  it.next();
17650  result << it.value();
17651  }
17652  return result;
17653 }
17654 
17676 {
17677  QCPAxis *newAxis = axis;
17678  if (!newAxis)
17679  {
17680  newAxis = new QCPAxis(this, type);
17681  } else // user provided existing axis instance, do some sanity checks
17682  {
17683  if (newAxis->axisType() != type)
17684  {
17685  qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter";
17686  return nullptr;
17687  }
17688  if (newAxis->axisRect() != this)
17689  {
17690  qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect";
17691  return nullptr;
17692  }
17693  if (axes().contains(newAxis))
17694  {
17695  qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect";
17696  return nullptr;
17697  }
17698  }
17699  if (!mAxes[type].isEmpty()) // multiple axes on one side, add half-bar axis ending to additional axes with offset
17700  {
17701  bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom);
17702  newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert));
17703  newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert));
17704  }
17705  mAxes[type].append(newAxis);
17706 
17707  // reset convenience axis pointers on parent QCustomPlot if they are unset:
17708  if (mParentPlot && mParentPlot->axisRectCount() > 0 && mParentPlot->axisRect(0) == this)
17709  {
17710  switch (type)
17711  {
17712  case QCPAxis::atBottom: { if (!mParentPlot->xAxis) mParentPlot->xAxis = newAxis; break; }
17713  case QCPAxis::atLeft: { if (!mParentPlot->yAxis) mParentPlot->yAxis = newAxis; break; }
17714  case QCPAxis::atTop: { if (!mParentPlot->xAxis2) mParentPlot->xAxis2 = newAxis; break; }
17715  case QCPAxis::atRight: { if (!mParentPlot->yAxis2) mParentPlot->yAxis2 = newAxis; break; }
17716  }
17717  }
17718 
17719  return newAxis;
17720 }
17721 
17730 QList<QCPAxis*> QCPAxisRect::addAxes(QCPAxis::AxisTypes types)
17731 {
17732  QList<QCPAxis*> result;
17733  if (types.testFlag(QCPAxis::atLeft))
17734  result << addAxis(QCPAxis::atLeft);
17735  if (types.testFlag(QCPAxis::atRight))
17736  result << addAxis(QCPAxis::atRight);
17737  if (types.testFlag(QCPAxis::atTop))
17738  result << addAxis(QCPAxis::atTop);
17739  if (types.testFlag(QCPAxis::atBottom))
17740  result << addAxis(QCPAxis::atBottom);
17741  return result;
17742 }
17743 
17752 {
17753  // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers:
17754  QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(mAxes);
17755  while (it.hasNext())
17756  {
17757  it.next();
17758  if (it.value().contains(axis))
17759  {
17760  if (it.value().first() == axis && it.value().size() > 1) // if removing first axis, transfer axis offset to the new first axis (which at this point is the second axis, if it exists)
17761  it.value()[1]->setOffset(axis->offset());
17762  mAxes[it.key()].removeOne(axis);
17763  if (qobject_cast<QCustomPlot*>(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot)
17765  delete axis;
17766  return true;
17767  }
17768  }
17769  qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast<quintptr>(axis);
17770  return false;
17771 }
17772 
17781 void QCPAxisRect::zoom(const QRectF &pixelRect)
17782 {
17783  zoom(pixelRect, axes());
17784 }
17785 
17794 void QCPAxisRect::zoom(const QRectF &pixelRect, const QList<QCPAxis*> &affectedAxes)
17795 {
17796  foreach (QCPAxis *axis, affectedAxes)
17797  {
17798  if (!axis)
17799  {
17800  qDebug() << Q_FUNC_INFO << "a passed axis was zero";
17801  continue;
17802  }
17803  QCPRange pixelRange;
17804  if (axis->orientation() == Qt::Horizontal)
17805  pixelRange = QCPRange(pixelRect.left(), pixelRect.right());
17806  else
17807  pixelRange = QCPRange(pixelRect.top(), pixelRect.bottom());
17808  axis->setRange(axis->pixelToCoord(pixelRange.lower), axis->pixelToCoord(pixelRange.upper));
17809  }
17810 }
17811 
17831 void QCPAxisRect::setupFullAxesBox(bool connectRanges)
17832 {
17833  QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
17834  if (axisCount(QCPAxis::atBottom) == 0)
17835  xAxis = addAxis(QCPAxis::atBottom);
17836  else
17837  xAxis = axis(QCPAxis::atBottom);
17838 
17839  if (axisCount(QCPAxis::atLeft) == 0)
17840  yAxis = addAxis(QCPAxis::atLeft);
17841  else
17842  yAxis = axis(QCPAxis::atLeft);
17843 
17844  if (axisCount(QCPAxis::atTop) == 0)
17845  xAxis2 = addAxis(QCPAxis::atTop);
17846  else
17847  xAxis2 = axis(QCPAxis::atTop);
17848 
17849  if (axisCount(QCPAxis::atRight) == 0)
17850  yAxis2 = addAxis(QCPAxis::atRight);
17851  else
17852  yAxis2 = axis(QCPAxis::atRight);
17853 
17854  xAxis->setVisible(true);
17855  yAxis->setVisible(true);
17856  xAxis2->setVisible(true);
17857  yAxis2->setVisible(true);
17858  xAxis2->setTickLabels(false);
17859  yAxis2->setTickLabels(false);
17860 
17861  xAxis2->setRange(xAxis->range());
17862  xAxis2->setRangeReversed(xAxis->rangeReversed());
17863  xAxis2->setScaleType(xAxis->scaleType());
17864  xAxis2->setTicks(xAxis->ticks());
17865  xAxis2->setNumberFormat(xAxis->numberFormat());
17866  xAxis2->setNumberPrecision(xAxis->numberPrecision());
17867  xAxis2->ticker()->setTickCount(xAxis->ticker()->tickCount());
17868  xAxis2->ticker()->setTickOrigin(xAxis->ticker()->tickOrigin());
17869 
17870  yAxis2->setRange(yAxis->range());
17871  yAxis2->setRangeReversed(yAxis->rangeReversed());
17872  yAxis2->setScaleType(yAxis->scaleType());
17873  yAxis2->setTicks(yAxis->ticks());
17874  yAxis2->setNumberFormat(yAxis->numberFormat());
17875  yAxis2->setNumberPrecision(yAxis->numberPrecision());
17876  yAxis2->ticker()->setTickCount(yAxis->ticker()->tickCount());
17877  yAxis2->ticker()->setTickOrigin(yAxis->ticker()->tickOrigin());
17878 
17879  if (connectRanges)
17880  {
17881  connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange)));
17882  connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange)));
17883  }
17884 }
17885 
17894 QList<QCPAbstractPlottable*> QCPAxisRect::plottables() const
17895 {
17896  // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries
17897  QList<QCPAbstractPlottable*> result;
17898  foreach (QCPAbstractPlottable *plottable, mParentPlot->mPlottables)
17899  {
17900  if (plottable->keyAxis()->axisRect() == this || plottable->valueAxis()->axisRect() == this)
17901  result.append(plottable);
17902  }
17903  return result;
17904 }
17905 
17914 QList<QCPGraph*> QCPAxisRect::graphs() const
17915 {
17916  // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries
17917  QList<QCPGraph*> result;
17918  foreach (QCPGraph *graph, mParentPlot->mGraphs)
17919  {
17920  if (graph->keyAxis()->axisRect() == this || graph->valueAxis()->axisRect() == this)
17921  result.append(graph);
17922  }
17923  return result;
17924 }
17925 
17936 QList<QCPAbstractItem *> QCPAxisRect::items() const
17937 {
17938  // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries
17939  // and miss those items that have this axis rect as clipAxisRect.
17940  QList<QCPAbstractItem*> result;
17941  foreach (QCPAbstractItem *item, mParentPlot->mItems)
17942  {
17943  if (item->clipAxisRect() == this)
17944  {
17945  result.append(item);
17946  continue;
17947  }
17948  foreach (QCPItemPosition *position, item->positions())
17949  {
17950  if (position->axisRect() == this ||
17951  position->keyAxis()->axisRect() == this ||
17952  position->valueAxis()->axisRect() == this)
17953  {
17954  result.append(item);
17955  break;
17956  }
17957  }
17958  }
17959  return result;
17960 }
17961 
17973 {
17974  QCPLayoutElement::update(phase);
17975 
17976  switch (phase)
17977  {
17978  case upPreparation:
17979  {
17980  foreach (QCPAxis *axis, axes())
17982  break;
17983  }
17984  case upLayout:
17985  {
17987  break;
17988  }
17989  default: break;
17990  }
17991 
17992  // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout):
17993  mInsetLayout->update(phase);
17994 }
17995 
17996 /* inherits documentation from base class */
17997 QList<QCPLayoutElement*> QCPAxisRect::elements(bool recursive) const
17998 {
17999  QList<QCPLayoutElement*> result;
18000  if (mInsetLayout)
18001  {
18002  result << mInsetLayout;
18003  if (recursive)
18004  result << mInsetLayout->elements(recursive);
18005  }
18006  return result;
18007 }
18008 
18009 /* inherits documentation from base class */
18011 {
18012  painter->setAntialiasing(false);
18013 }
18014 
18015 /* inherits documentation from base class */
18017 {
18018  drawBackground(painter);
18019 }
18020 
18036 void QCPAxisRect::setBackground(const QPixmap &pm)
18037 {
18038  mBackgroundPixmap = pm;
18039  mScaledBackgroundPixmap = QPixmap();
18040 }
18041 
18055 void QCPAxisRect::setBackground(const QBrush &brush)
18056 {
18057  mBackgroundBrush = brush;
18058 }
18059 
18067 void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
18068 {
18069  mBackgroundPixmap = pm;
18070  mScaledBackgroundPixmap = QPixmap();
18071  mBackgroundScaled = scaled;
18072  mBackgroundScaledMode = mode;
18073 }
18074 
18086 {
18087  mBackgroundScaled = scaled;
18088 }
18089 
18095 void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode)
18096 {
18097  mBackgroundScaledMode = mode;
18098 }
18099 
18106 QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation)
18107 {
18108  if (orientation == Qt::Horizontal)
18109  return mRangeDragHorzAxis.isEmpty() ? nullptr : mRangeDragHorzAxis.first().data();
18110  else
18111  return mRangeDragVertAxis.isEmpty() ? nullptr : mRangeDragVertAxis.first().data();
18112 }
18113 
18120 QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation)
18121 {
18122  if (orientation == Qt::Horizontal)
18123  return mRangeZoomHorzAxis.isEmpty() ? nullptr : mRangeZoomHorzAxis.first().data();
18124  else
18125  return mRangeZoomVertAxis.isEmpty() ? nullptr : mRangeZoomVertAxis.first().data();
18126 }
18127 
18133 QList<QCPAxis*> QCPAxisRect::rangeDragAxes(Qt::Orientation orientation)
18134 {
18135  QList<QCPAxis*> result;
18136  if (orientation == Qt::Horizontal)
18137  {
18138  foreach (QPointer<QCPAxis> axis, mRangeDragHorzAxis)
18139  {
18140  if (!axis.isNull())
18141  result.append(axis.data());
18142  }
18143  } else
18144  {
18145  foreach (QPointer<QCPAxis> axis, mRangeDragVertAxis)
18146  {
18147  if (!axis.isNull())
18148  result.append(axis.data());
18149  }
18150  }
18151  return result;
18152 }
18153 
18159 QList<QCPAxis*> QCPAxisRect::rangeZoomAxes(Qt::Orientation orientation)
18160 {
18161  QList<QCPAxis*> result;
18162  if (orientation == Qt::Horizontal)
18163  {
18164  foreach (QPointer<QCPAxis> axis, mRangeZoomHorzAxis)
18165  {
18166  if (!axis.isNull())
18167  result.append(axis.data());
18168  }
18169  } else
18170  {
18171  foreach (QPointer<QCPAxis> axis, mRangeZoomVertAxis)
18172  {
18173  if (!axis.isNull())
18174  result.append(axis.data());
18175  }
18176  }
18177  return result;
18178 }
18179 
18185 double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation)
18186 {
18187  return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert);
18188 }
18189 
18206 void QCPAxisRect::setRangeDrag(Qt::Orientations orientations)
18207 {
18208  mRangeDrag = orientations;
18209 }
18210 
18226 void QCPAxisRect::setRangeZoom(Qt::Orientations orientations)
18227 {
18228  mRangeZoom = orientations;
18229 }
18230 
18242 void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical)
18243 {
18244  QList<QCPAxis*> horz, vert;
18245  if (horizontal)
18246  horz.append(horizontal);
18247  if (vertical)
18248  vert.append(vertical);
18249  setRangeDragAxes(horz, vert);
18250 }
18251 
18261 void QCPAxisRect::setRangeDragAxes(QList<QCPAxis*> axes)
18262 {
18263  QList<QCPAxis*> horz, vert;
18264  foreach (QCPAxis *ax, axes)
18265  {
18266  if (ax->orientation() == Qt::Horizontal)
18267  horz.append(ax);
18268  else
18269  vert.append(ax);
18270  }
18271  setRangeDragAxes(horz, vert);
18272 }
18273 
18280 void QCPAxisRect::setRangeDragAxes(QList<QCPAxis*> horizontal, QList<QCPAxis*> vertical)
18281 {
18282  mRangeDragHorzAxis.clear();
18283  foreach (QCPAxis *ax, horizontal)
18284  {
18285  QPointer<QCPAxis> axPointer(ax);
18286  if (!axPointer.isNull())
18287  mRangeDragHorzAxis.append(axPointer);
18288  else
18289  qDebug() << Q_FUNC_INFO << "invalid axis passed in horizontal list:" << reinterpret_cast<quintptr>(ax);
18290  }
18291  mRangeDragVertAxis.clear();
18292  foreach (QCPAxis *ax, vertical)
18293  {
18294  QPointer<QCPAxis> axPointer(ax);
18295  if (!axPointer.isNull())
18296  mRangeDragVertAxis.append(axPointer);
18297  else
18298  qDebug() << Q_FUNC_INFO << "invalid axis passed in vertical list:" << reinterpret_cast<quintptr>(ax);
18299  }
18300 }
18301 
18314 void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical)
18315 {
18316  QList<QCPAxis*> horz, vert;
18317  if (horizontal)
18318  horz.append(horizontal);
18319  if (vertical)
18320  vert.append(vertical);
18321  setRangeZoomAxes(horz, vert);
18322 }
18323 
18333 void QCPAxisRect::setRangeZoomAxes(QList<QCPAxis*> axes)
18334 {
18335  QList<QCPAxis*> horz, vert;
18336  foreach (QCPAxis *ax, axes)
18337  {
18338  if (ax->orientation() == Qt::Horizontal)
18339  horz.append(ax);
18340  else
18341  vert.append(ax);
18342  }
18343  setRangeZoomAxes(horz, vert);
18344 }
18345 
18352 void QCPAxisRect::setRangeZoomAxes(QList<QCPAxis*> horizontal, QList<QCPAxis*> vertical)
18353 {
18354  mRangeZoomHorzAxis.clear();
18355  foreach (QCPAxis *ax, horizontal)
18356  {
18357  QPointer<QCPAxis> axPointer(ax);
18358  if (!axPointer.isNull())
18359  mRangeZoomHorzAxis.append(axPointer);
18360  else
18361  qDebug() << Q_FUNC_INFO << "invalid axis passed in horizontal list:" << reinterpret_cast<quintptr>(ax);
18362  }
18363  mRangeZoomVertAxis.clear();
18364  foreach (QCPAxis *ax, vertical)
18365  {
18366  QPointer<QCPAxis> axPointer(ax);
18367  if (!axPointer.isNull())
18368  mRangeZoomVertAxis.append(axPointer);
18369  else
18370  qDebug() << Q_FUNC_INFO << "invalid axis passed in vertical list:" << reinterpret_cast<quintptr>(ax);
18371  }
18372 }
18373 
18384 void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor)
18385 {
18386  mRangeZoomFactorHorz = horizontalFactor;
18387  mRangeZoomFactorVert = verticalFactor;
18388 }
18389 
18395 {
18396  mRangeZoomFactorHorz = factor;
18397  mRangeZoomFactorVert = factor;
18398 }
18399 
18419 {
18420  // draw background fill:
18421  if (mBackgroundBrush != Qt::NoBrush)
18422  painter->fillRect(mRect, mBackgroundBrush);
18423 
18424  // draw background pixmap (on top of fill, if brush specified):
18425  if (!mBackgroundPixmap.isNull())
18426  {
18427  if (mBackgroundScaled)
18428  {
18429  // check whether mScaledBackground needs to be updated:
18430  QSize scaledSize(mBackgroundPixmap.size());
18431  scaledSize.scale(mRect.size(), mBackgroundScaledMode);
18432  if (mScaledBackgroundPixmap.size() != scaledSize)
18433  mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
18434  painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect());
18435  } else
18436  {
18437  painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()));
18438  }
18439  }
18440 }
18441 
18453 {
18454  const QList<QCPAxis*> axesList = mAxes.value(type);
18455  if (axesList.isEmpty())
18456  return;
18457 
18458  bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false
18459  for (int i=1; i<axesList.size(); ++i)
18460  {
18461  int offset = axesList.at(i-1)->offset() + axesList.at(i-1)->calculateMargin();
18462  if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible)
18463  {
18464  if (!isFirstVisible)
18465  offset += axesList.at(i)->tickLengthIn();
18466  isFirstVisible = false;
18467  }
18468  axesList.at(i)->setOffset(offset);
18469  }
18470 }
18471 
18472 /* inherits documentation from base class */
18474 {
18475  if (!mAutoMargins.testFlag(side))
18476  qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin";
18477 
18479 
18480  // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call
18481  const QList<QCPAxis*> axesList = mAxes.value(QCPAxis::marginSideToAxisType(side));
18482  if (!axesList.isEmpty())
18483  return axesList.last()->offset() + axesList.last()->calculateMargin();
18484  else
18485  return 0;
18486 }
18487 
18499 {
18500  if (mParentPlot && mParentPlot->axisRectCount() > 0 && mParentPlot->axisRect(0) == this)
18501  {
18510  }
18511 }
18512 
18524 void QCPAxisRect::mousePressEvent(QMouseEvent *event, const QVariant &details)
18525 {
18526  Q_UNUSED(details)
18527  if (event->buttons() & Qt::LeftButton)
18528  {
18529  mDragging = true;
18530  // initialize antialiasing backup in case we start dragging:
18532  {
18535  }
18536  // Mouse range dragging interaction:
18537  if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
18538  {
18539  mDragStartHorzRange.clear();
18540  foreach (QPointer<QCPAxis> axis, mRangeDragHorzAxis)
18541  mDragStartHorzRange.append(axis.isNull() ? QCPRange() : axis->range());
18542  mDragStartVertRange.clear();
18543  foreach (QPointer<QCPAxis> axis, mRangeDragVertAxis)
18544  mDragStartVertRange.append(axis.isNull() ? QCPRange() : axis->range());
18545  }
18546  }
18547 }
18548 
18556 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
18557 {
18558  Q_UNUSED(startPos)
18559  // Mouse range dragging interaction:
18560  if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag))
18561  {
18562 
18563  if (mRangeDrag.testFlag(Qt::Horizontal))
18564  {
18565  for (int i=0; i<mRangeDragHorzAxis.size(); ++i)
18566  {
18567  QCPAxis *ax = mRangeDragHorzAxis.at(i).data();
18568  if (!ax)
18569  continue;
18570  if (i >= mDragStartHorzRange.size())
18571  break;
18572  if (ax->mScaleType == QCPAxis::stLinear)
18573  {
18574  double diff = ax->pixelToCoord(startPos.x()) - ax->pixelToCoord(event->pos().x());
18575  ax->setRange(mDragStartHorzRange.at(i).lower+diff, mDragStartHorzRange.at(i).upper+diff);
18576  } else if (ax->mScaleType == QCPAxis::stLogarithmic)
18577  {
18578  double diff = ax->pixelToCoord(startPos.x()) / ax->pixelToCoord(event->pos().x());
18579  ax->setRange(mDragStartHorzRange.at(i).lower*diff, mDragStartHorzRange.at(i).upper*diff);
18580  }
18581  }
18582  }
18583 
18584  if (mRangeDrag.testFlag(Qt::Vertical))
18585  {
18586  for (int i=0; i<mRangeDragVertAxis.size(); ++i)
18587  {
18588  QCPAxis *ax = mRangeDragVertAxis.at(i).data();
18589  if (!ax)
18590  continue;
18591  if (i >= mDragStartVertRange.size())
18592  break;
18593  if (ax->mScaleType == QCPAxis::stLinear)
18594  {
18595  double diff = ax->pixelToCoord(startPos.y()) - ax->pixelToCoord(event->pos().y());
18596  ax->setRange(mDragStartVertRange.at(i).lower+diff, mDragStartVertRange.at(i).upper+diff);
18597  } else if (ax->mScaleType == QCPAxis::stLogarithmic)
18598  {
18599  double diff = ax->pixelToCoord(startPos.y()) / ax->pixelToCoord(event->pos().y());
18600  ax->setRange(mDragStartVertRange.at(i).lower*diff, mDragStartVertRange.at(i).upper*diff);
18601  }
18602  }
18603  }
18604 
18605  if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot
18606  {
18610  }
18611 
18612  }
18613 }
18614 
18615 /* inherits documentation from base class */
18616 void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
18617 {
18618  Q_UNUSED(event)
18619  Q_UNUSED(startPos)
18620  mDragging = false;
18622  {
18625  }
18626 }
18627 
18642 void QCPAxisRect::wheelEvent(QWheelEvent *event)
18643 {
18644 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
18645  const double delta = event->delta();
18646 #else
18647  const double delta = event->angleDelta().y();
18648 #endif
18649 
18650 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
18651  const QPointF pos = event->pos();
18652 #else
18653  const QPointF pos = event->position();
18654 #endif
18655 
18656  // Mouse range zooming interaction:
18657  if (mParentPlot->interactions().testFlag(QCP::iRangeZoom))
18658  {
18659  if (mRangeZoom != 0)
18660  {
18661  double factor;
18662  double wheelSteps = delta/120.0; // a single step delta is +/-120 usually
18663  if (mRangeZoom.testFlag(Qt::Horizontal))
18664  {
18665  factor = qPow(mRangeZoomFactorHorz, wheelSteps);
18666  foreach (QPointer<QCPAxis> axis, mRangeZoomHorzAxis)
18667  {
18668  if (!axis.isNull())
18669  axis->scaleRange(factor, axis->pixelToCoord(pos.x()));
18670  }
18671  }
18672  if (mRangeZoom.testFlag(Qt::Vertical))
18673  {
18674  factor = qPow(mRangeZoomFactorVert, wheelSteps);
18675  foreach (QPointer<QCPAxis> axis, mRangeZoomVertAxis)
18676  {
18677  if (!axis.isNull())
18678  axis->scaleRange(factor, axis->pixelToCoord(pos.y()));
18679  }
18680  }
18681  mParentPlot->replot();
18682  }
18683  }
18684 }
18685 /* end of 'src/layoutelements/layoutelement-axisrect.cpp' */
18686 
18687 
18688 /* including file 'src/layoutelements/layoutelement-legend.cpp' */
18689 /* modified 2021-03-29T02:30:44, size 31762 */
18690 
18694 
18719 /* start of documentation of signals */
18720 
18727 /* end of documentation of signals */
18728 
18734  QCPLayoutElement(parent->parentPlot()),
18735  mParentLegend(parent),
18736  mFont(parent->font()),
18737  mTextColor(parent->textColor()),
18738  mSelectedFont(parent->selectedFont()),
18739  mSelectedTextColor(parent->selectedTextColor()),
18740  mSelectable(true),
18741  mSelected(false)
18742 {
18743  setLayer(QLatin1String("legend"));
18744  setMargins(QMargins(0, 0, 0, 0));
18745 }
18746 
18752 void QCPAbstractLegendItem::setFont(const QFont &font)
18753 {
18754  mFont = font;
18755 }
18756 
18763 {
18764  mTextColor = color;
18765 }
18766 
18774 {
18775  mSelectedFont = font;
18776 }
18777 
18785 {
18787 }
18788 
18795 {
18796  if (mSelectable != selectable)
18797  {
18800  }
18801 }
18802 
18812 {
18813  if (mSelected != selected)
18814  {
18815  mSelected = selected;
18817  }
18818 }
18819 
18820 /* inherits documentation from base class */
18821 double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
18822 {
18823  Q_UNUSED(details)
18824  if (!mParentPlot) return -1;
18825  if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems)))
18826  return -1;
18827 
18828  if (mRect.contains(pos.toPoint()))
18829  return mParentPlot->selectionTolerance()*0.99;
18830  else
18831  return -1;
18832 }
18833 
18834 /* inherits documentation from base class */
18836 {
18838 }
18839 
18840 /* inherits documentation from base class */
18842 {
18843  return mOuterRect;
18844 }
18845 
18846 /* inherits documentation from base class */
18847 void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
18848 {
18849  Q_UNUSED(event)
18850  Q_UNUSED(details)
18852  {
18853  bool selBefore = mSelected;
18854  setSelected(additive ? !mSelected : true);
18855  if (selectionStateChanged)
18856  *selectionStateChanged = mSelected != selBefore;
18857  }
18858 }
18859 
18860 /* inherits documentation from base class */
18861 void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged)
18862 {
18864  {
18865  bool selBefore = mSelected;
18866  setSelected(false);
18867  if (selectionStateChanged)
18868  *selectionStateChanged = mSelected != selBefore;
18869  }
18870 }
18871 
18875 
18908  QCPAbstractLegendItem(parent),
18909  mPlottable(plottable)
18910 {
18911  setAntialiased(false);
18912 }
18913 
18920 {
18922 }
18923 
18930 {
18932 }
18933 
18940 {
18941  return mSelected ? mSelectedFont : mFont;
18942 }
18943 
18951 {
18952  if (!mPlottable) return;
18953  painter->setFont(getFont());
18954  painter->setPen(QPen(getTextColor()));
18955  QSize iconSize = mParentLegend->iconSize();
18956  QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
18957  QRect iconRect(mRect.topLeft(), iconSize);
18958  int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops
18959  painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name());
18960  // draw icon:
18961  painter->save();
18962  painter->setClipRect(iconRect, Qt::IntersectClip);
18963  mPlottable->drawLegendIcon(painter, iconRect);
18964  painter->restore();
18965  // draw icon border:
18966  if (getIconBorderPen().style() != Qt::NoPen)
18967  {
18968  painter->setPen(getIconBorderPen());
18969  painter->setBrush(Qt::NoBrush);
18970  int halfPen = qCeil(painter->pen().widthF()*0.5)+1;
18971  painter->setClipRect(mOuterRect.adjusted(-halfPen, -halfPen, halfPen, halfPen)); // extend default clip rect so thicker pens (especially during selection) are not clipped
18972  painter->drawRect(iconRect);
18973  }
18974 }
18975 
18984 {
18985  if (!mPlottable) return {};
18986  QSize result(0, 0);
18987  QRect textRect;
18988  QFontMetrics fontMetrics(getFont());
18989  QSize iconSize = mParentLegend->iconSize();
18990  textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name());
18991  result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width());
18992  result.setHeight(qMax(textRect.height(), iconSize.height()));
18993  result.rwidth() += mMargins.left()+mMargins.right();
18994  result.rheight() += mMargins.top()+mMargins.bottom();
18995  return result;
18996 }
18997 
18998 
19002 
19037 /* start of documentation of signals */
19038 
19046 /* end of documentation of signals */
19047 
19055  mIconTextPadding{}
19056 {
19057  setFillOrder(QCPLayoutGrid::foRowsFirst);
19058  setWrap(0);
19059 
19060  setRowSpacing(3);
19061  setColumnSpacing(8);
19062  setMargins(QMargins(7, 5, 7, 4));
19063  setAntialiased(false);
19064  setIconSize(32, 18);
19065 
19066  setIconTextPadding(7);
19067 
19068  setSelectableParts(spLegendBox | spItems);
19069  setSelectedParts(spNone);
19070 
19071  setBorderPen(QPen(Qt::black, 0));
19072  setSelectedBorderPen(QPen(Qt::blue, 2));
19073  setIconBorderPen(Qt::NoPen);
19074  setSelectedIconBorderPen(QPen(Qt::blue, 2));
19075  setBrush(Qt::white);
19076  setSelectedBrush(Qt::white);
19077  setTextColor(Qt::black);
19078  setSelectedTextColor(Qt::blue);
19079 }
19080 
19082 {
19083  clearItems();
19084  if (qobject_cast<QCustomPlot*>(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot)
19085  mParentPlot->legendRemoved(this);
19086 }
19087 
19088 /* no doc for getter, see setSelectedParts */
19089 QCPLegend::SelectableParts QCPLegend::selectedParts() const
19090 {
19091  // check whether any legend elements selected, if yes, add spItems to return value
19092  bool hasSelectedItems = false;
19093  for (int i=0; i<itemCount(); ++i)
19094  {
19095  if (item(i) && item(i)->selected())
19096  {
19097  hasSelectedItems = true;
19098  break;
19099  }
19100  }
19101  if (hasSelectedItems)
19102  return mSelectedParts | spItems;
19103  else
19104  return mSelectedParts & ~spItems;
19105 }
19106 
19110 void QCPLegend::setBorderPen(const QPen &pen)
19111 {
19112  mBorderPen = pen;
19113 }
19114 
19118 void QCPLegend::setBrush(const QBrush &brush)
19119 {
19120  mBrush = brush;
19121 }
19122 
19132 void QCPLegend::setFont(const QFont &font)
19133 {
19134  mFont = font;
19135  for (int i=0; i<itemCount(); ++i)
19136  {
19137  if (item(i))
19138  item(i)->setFont(mFont);
19139  }
19140 }
19141 
19151 void QCPLegend::setTextColor(const QColor &color)
19152 {
19153  mTextColor = color;
19154  for (int i=0; i<itemCount(); ++i)
19155  {
19156  if (item(i))
19157  item(i)->setTextColor(color);
19158  }
19159 }
19160 
19165 void QCPLegend::setIconSize(const QSize &size)
19166 {
19167  mIconSize = size;
19168 }
19169 
19172 void QCPLegend::setIconSize(int width, int height)
19173 {
19174  mIconSize.setWidth(width);
19175  mIconSize.setHeight(height);
19176 }
19177 
19184 {
19185  mIconTextPadding = padding;
19186 }
19187 
19194 void QCPLegend::setIconBorderPen(const QPen &pen)
19195 {
19196  mIconBorderPen = pen;
19197 }
19198 
19209 void QCPLegend::setSelectableParts(const SelectableParts &selectable)
19210 {
19211  if (mSelectableParts != selectable)
19212  {
19213  mSelectableParts = selectable;
19215  }
19216 }
19217 
19239 void QCPLegend::setSelectedParts(const SelectableParts &selected)
19240 {
19241  SelectableParts newSelected = selected;
19242  mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed
19243 
19244  if (mSelectedParts != newSelected)
19245  {
19246  if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that)
19247  {
19248  qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function";
19249  newSelected &= ~spItems;
19250  }
19251  if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection
19252  {
19253  for (int i=0; i<itemCount(); ++i)
19254  {
19255  if (item(i))
19256  item(i)->setSelected(false);
19257  }
19258  }
19259  mSelectedParts = newSelected;
19261  }
19262 }
19263 
19270 void QCPLegend::setSelectedBorderPen(const QPen &pen)
19271 {
19272  mSelectedBorderPen = pen;
19273 }
19274 
19281 {
19282  mSelectedIconBorderPen = pen;
19283 }
19284 
19291 void QCPLegend::setSelectedBrush(const QBrush &brush)
19292 {
19294 }
19295 
19303 void QCPLegend::setSelectedFont(const QFont &font)
19304 {
19305  mSelectedFont = font;
19306  for (int i=0; i<itemCount(); ++i)
19307  {
19308  if (item(i))
19309  item(i)->setSelectedFont(font);
19310  }
19311 }
19312 
19321 {
19323  for (int i=0; i<itemCount(); ++i)
19324  {
19325  if (item(i))
19327  }
19328 }
19329 
19339 {
19340  return qobject_cast<QCPAbstractLegendItem*>(elementAt(index));
19341 }
19342 
19350 {
19351  for (int i=0; i<itemCount(); ++i)
19352  {
19353  if (QCPPlottableLegendItem *pli = qobject_cast<QCPPlottableLegendItem*>(item(i)))
19354  {
19355  if (pli->plottable() == plottable)
19356  return pli;
19357  }
19358  }
19359  return nullptr;
19360 }
19361 
19373 {
19374  return elementCount();
19375 }
19376 
19383 {
19384  for (int i=0; i<itemCount(); ++i)
19385  {
19386  if (item == this->item(i))
19387  return true;
19388  }
19389  return false;
19390 }
19391 
19399 {
19400  return itemWithPlottable(plottable);
19401 }
19402 
19414 {
19415  return addElement(item);
19416 }
19417 
19431 bool QCPLegend::removeItem(int index)
19432 {
19433  if (QCPAbstractLegendItem *ali = item(index))
19434  {
19435  bool success = remove(ali);
19436  if (success)
19437  setFillOrder(fillOrder(), true); // gets rid of empty cell by reordering
19438  return success;
19439  } else
19440  return false;
19441 }
19442 
19456 {
19457  bool success = remove(item);
19458  if (success)
19459  setFillOrder(fillOrder(), true); // gets rid of empty cell by reordering
19460  return success;
19461 }
19462 
19467 {
19468  for (int i=elementCount()-1; i>=0; --i)
19469  {
19470  if (item(i))
19471  removeAt(i); // don't use removeItem() because it would unnecessarily reorder the whole legend for each item
19472  }
19473  setFillOrder(fillOrder(), true); // get rid of empty cells by reordering once after all items are removed
19474 }
19475 
19482 QList<QCPAbstractLegendItem *> QCPLegend::selectedItems() const
19483 {
19484  QList<QCPAbstractLegendItem*> result;
19485  for (int i=0; i<itemCount(); ++i)
19486  {
19487  if (QCPAbstractLegendItem *ali = item(i))
19488  {
19489  if (ali->selected())
19490  result.append(ali);
19491  }
19492  }
19493  return result;
19494 }
19495 
19512 {
19514 }
19515 
19522 {
19524 }
19525 
19531 QBrush QCPLegend::getBrush() const
19532 {
19533  return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush;
19534 }
19535 
19542 {
19543  // draw background rect:
19544  painter->setBrush(getBrush());
19545  painter->setPen(getBorderPen());
19546  painter->drawRect(mOuterRect);
19547 }
19548 
19549 /* inherits documentation from base class */
19550 double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
19551 {
19552  if (!mParentPlot) return -1;
19553  if (onlySelectable && !mSelectableParts.testFlag(spLegendBox))
19554  return -1;
19555 
19556  if (mOuterRect.contains(pos.toPoint()))
19557  {
19558  if (details) details->setValue(spLegendBox);
19559  return mParentPlot->selectionTolerance()*0.99;
19560  }
19561  return -1;
19562 }
19563 
19564 /* inherits documentation from base class */
19565 void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
19566 {
19567  Q_UNUSED(event)
19568  mSelectedParts = selectedParts(); // in case item selection has changed
19569  if (details.value<SelectablePart>() == spLegendBox && mSelectableParts.testFlag(spLegendBox))
19570  {
19571  SelectableParts selBefore = mSelectedParts;
19572  setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent)
19573  if (selectionStateChanged)
19574  *selectionStateChanged = mSelectedParts != selBefore;
19575  }
19576 }
19577 
19578 /* inherits documentation from base class */
19579 void QCPLegend::deselectEvent(bool *selectionStateChanged)
19580 {
19581  mSelectedParts = selectedParts(); // in case item selection has changed
19582  if (mSelectableParts.testFlag(spLegendBox))
19583  {
19584  SelectableParts selBefore = mSelectedParts;
19586  if (selectionStateChanged)
19587  *selectionStateChanged = mSelectedParts != selBefore;
19588  }
19589 }
19590 
19591 /* inherits documentation from base class */
19593 {
19594  return QCP::iSelectLegend;
19595 }
19596 
19597 /* inherits documentation from base class */
19599 {
19600  return QCP::iSelectLegend;
19601 }
19602 
19603 /* inherits documentation from base class */
19605 {
19606  if (parentPlot && !parentPlot->legend)
19607  parentPlot->legend = this;
19608 }
19609 /* end of 'src/layoutelements/layoutelement-legend.cpp' */
19610 
19611 
19612 /* including file 'src/layoutelements/layoutelement-textelement.cpp' */
19613 /* modified 2021-03-29T02:30:44, size 12925 */
19614 
19618 
19629 /* start documentation of signals */
19630 
19653 /* end documentation of signals */
19654 
19661  QCPLayoutElement(parentPlot),
19662  mText(),
19663  mTextFlags(Qt::AlignCenter),
19664  mFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below
19665  mTextColor(Qt::black),
19666  mSelectedFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below
19667  mSelectedTextColor(Qt::blue),
19668  mSelectable(false),
19669  mSelected(false)
19670 {
19671  if (parentPlot)
19672  {
19673  mFont = parentPlot->font();
19674  mSelectedFont = parentPlot->font();
19675  }
19676  setMargins(QMargins(2, 2, 2, 2));
19677 }
19678 
19685 QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text) :
19686  QCPLayoutElement(parentPlot),
19687  mText(text),
19688  mTextFlags(Qt::AlignCenter),
19689  mFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below
19690  mTextColor(Qt::black),
19691  mSelectedFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below
19692  mSelectedTextColor(Qt::blue),
19693  mSelectable(false),
19694  mSelected(false)
19695 {
19696  if (parentPlot)
19697  {
19698  mFont = parentPlot->font();
19699  mSelectedFont = parentPlot->font();
19700  }
19701  setMargins(QMargins(2, 2, 2, 2));
19702 }
19703 
19710 QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text, double pointSize) :
19711  QCPLayoutElement(parentPlot),
19712  mText(text),
19713  mTextFlags(Qt::AlignCenter),
19714  mFont(QFont(QLatin1String("sans serif"), int(pointSize))), // will be taken from parentPlot if available, see below
19715  mTextColor(Qt::black),
19716  mSelectedFont(QFont(QLatin1String("sans serif"), int(pointSize))), // will be taken from parentPlot if available, see below
19717  mSelectedTextColor(Qt::blue),
19718  mSelectable(false),
19719  mSelected(false)
19720 {
19721  mFont.setPointSizeF(pointSize); // set here again as floating point, because constructor above only takes integer
19722  if (parentPlot)
19723  {
19724  mFont = parentPlot->font();
19725  mFont.setPointSizeF(pointSize);
19726  mSelectedFont = parentPlot->font();
19727  mSelectedFont.setPointSizeF(pointSize);
19728  }
19729  setMargins(QMargins(2, 2, 2, 2));
19730 }
19731 
19738 QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text, const QString &fontFamily, double pointSize) :
19739  QCPLayoutElement(parentPlot),
19740  mText(text),
19741  mTextFlags(Qt::AlignCenter),
19742  mFont(QFont(fontFamily, int(pointSize))),
19743  mTextColor(Qt::black),
19744  mSelectedFont(QFont(fontFamily, int(pointSize))),
19745  mSelectedTextColor(Qt::blue),
19746  mSelectable(false),
19747  mSelected(false)
19748 {
19749  mFont.setPointSizeF(pointSize); // set here again as floating point, because constructor above only takes integer
19750  setMargins(QMargins(2, 2, 2, 2));
19751 }
19752 
19759 QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text, const QFont &font) :
19760  QCPLayoutElement(parentPlot),
19761  mText(text),
19762  mTextFlags(Qt::AlignCenter),
19763  mFont(font),
19764  mTextColor(Qt::black),
19765  mSelectedFont(font),
19766  mSelectedTextColor(Qt::blue),
19767  mSelectable(false),
19768  mSelected(false)
19769 {
19770  setMargins(QMargins(2, 2, 2, 2));
19771 }
19772 
19778 void QCPTextElement::setText(const QString &text)
19779 {
19780  mText = text;
19781 }
19782 
19804 {
19805  mTextFlags = flags;
19806 }
19807 
19813 void QCPTextElement::setFont(const QFont &font)
19814 {
19815  mFont = font;
19816 }
19817 
19824 {
19825  mTextColor = color;
19826 }
19827 
19833 void QCPTextElement::setSelectedFont(const QFont &font)
19834 {
19835  mSelectedFont = font;
19836 }
19837 
19844 {
19846 }
19847 
19854 void QCPTextElement::setSelectable(bool selectable)
19855 {
19856  if (mSelectable != selectable)
19857  {
19860  }
19861 }
19862 
19870 void QCPTextElement::setSelected(bool selected)
19871 {
19872  if (mSelected != selected)
19873  {
19874  mSelected = selected;
19876  }
19877 }
19878 
19879 /* inherits documentation from base class */
19881 {
19883 }
19884 
19885 /* inherits documentation from base class */
19887 {
19888  painter->setFont(mainFont());
19889  painter->setPen(QPen(mainTextColor()));
19890  painter->drawText(mRect, mTextFlags, mText, &mTextBoundingRect);
19891 }
19892 
19893 /* inherits documentation from base class */
19895 {
19896  QFontMetrics metrics(mFont);
19897  QSize result(metrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, mText).size());
19898  result.rwidth() += mMargins.left()+mMargins.right();
19899  result.rheight() += mMargins.top()+mMargins.bottom();
19900  return result;
19901 }
19902 
19903 /* inherits documentation from base class */
19905 {
19906  QFontMetrics metrics(mFont);
19907  QSize result(metrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, mText).size());
19908  result.setWidth(QWIDGETSIZE_MAX);
19909  result.rheight() += mMargins.top()+mMargins.bottom();
19910  return result;
19911 }
19912 
19913 /* inherits documentation from base class */
19914 void QCPTextElement::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
19915 {
19916  Q_UNUSED(event)
19917  Q_UNUSED(details)
19918  if (mSelectable)
19919  {
19920  bool selBefore = mSelected;
19921  setSelected(additive ? !mSelected : true);
19922  if (selectionStateChanged)
19923  *selectionStateChanged = mSelected != selBefore;
19924  }
19925 }
19926 
19927 /* inherits documentation from base class */
19928 void QCPTextElement::deselectEvent(bool *selectionStateChanged)
19929 {
19930  if (mSelectable)
19931  {
19932  bool selBefore = mSelected;
19933  setSelected(false);
19934  if (selectionStateChanged)
19935  *selectionStateChanged = mSelected != selBefore;
19936  }
19937 }
19938 
19949 double QCPTextElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
19950 {
19951  Q_UNUSED(details)
19952  if (onlySelectable && !mSelectable)
19953  return -1;
19954 
19955  if (mTextBoundingRect.contains(pos.toPoint()))
19956  return mParentPlot->selectionTolerance()*0.99;
19957  else
19958  return -1;
19959 }
19960 
19967 void QCPTextElement::mousePressEvent(QMouseEvent *event, const QVariant &details)
19968 {
19969  Q_UNUSED(details)
19970  event->accept();
19971 }
19972 
19979 void QCPTextElement::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
19980 {
19981  if ((QPointF(event->pos())-startPos).manhattanLength() <= 3)
19982  emit clicked(event);
19983 }
19984 
19990 void QCPTextElement::mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details)
19991 {
19992  Q_UNUSED(details)
19993  emit doubleClicked(event);
19994 }
19995 
20002 {
20003  return mSelected ? mSelectedFont : mFont;
20004 }
20005 
20012 {
20014 }
20015 /* end of 'src/layoutelements/layoutelement-textelement.cpp' */
20016 
20017 
20018 /* including file 'src/layoutelements/layoutelement-colorscale.cpp' */
20019 /* modified 2021-03-29T02:30:44, size 26531 */
20020 
20021 
20025 
20064 /* start documentation of inline functions */
20065 
20079 /* end documentation of signals */
20080 /* start documentation of signals */
20081 
20103 /* end documentation of signals */
20104 
20109  QCPLayoutElement(parentPlot),
20110  mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight
20111  mDataScaleType(QCPAxis::stLinear),
20112  mGradient(QCPColorGradient::gpCold),
20113  mBarWidth(20),
20114  mAxisRect(new QCPColorScaleAxisRectPrivate(this))
20115 {
20116  setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used)
20118  setDataRange(QCPRange(0, 6));
20119 }
20120 
20122 {
20123  delete mAxisRect;
20124 }
20125 
20126 /* undocumented getter */
20127 QString QCPColorScale::label() const
20128 {
20129  if (!mColorAxis)
20130  {
20131  qDebug() << Q_FUNC_INFO << "internal color axis undefined";
20132  return QString();
20133  }
20134 
20135  return mColorAxis.data()->label();
20136 }
20137 
20138 /* undocumented getter */
20140 {
20141  if (!mAxisRect)
20142  {
20143  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20144  return false;
20145  }
20146 
20147  return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) &&
20148  mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) &&
20149  mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
20150 }
20151 
20152 /* undocumented getter */
20154 {
20155  if (!mAxisRect)
20156  {
20157  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20158  return false;
20159  }
20160 
20161  return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) &&
20162  mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) &&
20163  mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType);
20164 }
20165 
20174 {
20175  if (!mAxisRect)
20176  {
20177  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20178  return;
20179  }
20180  if (mType != type)
20181  {
20182  mType = type;
20183  QCPRange rangeTransfer(0, 6);
20184  QString labelTransfer;
20185  QSharedPointer<QCPAxisTicker> tickerTransfer;
20186  // transfer/revert some settings on old axis if it exists:
20187  bool doTransfer = !mColorAxis.isNull();
20188  if (doTransfer)
20189  {
20190  rangeTransfer = mColorAxis.data()->range();
20191  labelTransfer = mColorAxis.data()->label();
20192  tickerTransfer = mColorAxis.data()->ticker();
20193  mColorAxis.data()->setLabel(QString());
20194  disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20195  disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20196  }
20197  const QList<QCPAxis::AxisType> allAxisTypes = QList<QCPAxis::AxisType>() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop;
20198  foreach (QCPAxis::AxisType atype, allAxisTypes)
20199  {
20200  mAxisRect.data()->axis(atype)->setTicks(atype == mType);
20201  mAxisRect.data()->axis(atype)->setTickLabels(atype== mType);
20202  }
20203  // set new mColorAxis pointer:
20204  mColorAxis = mAxisRect.data()->axis(mType);
20205  // transfer settings to new axis:
20206  if (doTransfer)
20207  {
20208  mColorAxis.data()->setRange(rangeTransfer); // range transfer necessary if axis changes from vertical to horizontal or vice versa (axes with same orientation are synchronized via signals)
20209  mColorAxis.data()->setLabel(labelTransfer);
20210  mColorAxis.data()->setTicker(tickerTransfer);
20211  }
20212  connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
20213  connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
20214  mAxisRect.data()->setRangeDragAxes(QList<QCPAxis*>() << mColorAxis.data());
20215  }
20216 }
20217 
20228 {
20230  {
20232  if (mColorAxis)
20233  mColorAxis.data()->setRange(mDataRange);
20235  }
20236 }
20237 
20258 {
20259  if (mDataScaleType != scaleType)
20260  {
20261  mDataScaleType = scaleType;
20262  if (mColorAxis)
20263  mColorAxis.data()->setScaleType(mDataScaleType);
20267  }
20268 }
20269 
20278 {
20279  if (mGradient != gradient)
20280  {
20281  mGradient = gradient;
20282  if (mAxisRect)
20283  mAxisRect.data()->mGradientImageInvalidated = true;
20284  emit gradientChanged(mGradient);
20285  }
20286 }
20287 
20292 void QCPColorScale::setLabel(const QString &str)
20293 {
20294  if (!mColorAxis)
20295  {
20296  qDebug() << Q_FUNC_INFO << "internal color axis undefined";
20297  return;
20298  }
20299 
20300  mColorAxis.data()->setLabel(str);
20301 }
20302 
20308 {
20309  mBarWidth = width;
20310 }
20311 
20319 {
20320  if (!mAxisRect)
20321  {
20322  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20323  return;
20324  }
20325 
20326  if (enabled)
20327  {
20328  mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType));
20329  } else
20330  {
20331 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
20332  mAxisRect.data()->setRangeDrag(nullptr);
20333 #else
20334  mAxisRect.data()->setRangeDrag({});
20335 #endif
20336  }
20337 }
20338 
20346 {
20347  if (!mAxisRect)
20348  {
20349  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20350  return;
20351  }
20352 
20353  if (enabled)
20354  {
20355  mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType));
20356  } else
20357  {
20358 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
20359  mAxisRect.data()->setRangeDrag(nullptr);
20360 #else
20361  mAxisRect.data()->setRangeZoom({});
20362 #endif
20363  }
20364 }
20365 
20369 QList<QCPColorMap*> QCPColorScale::colorMaps() const
20370 {
20371  QList<QCPColorMap*> result;
20372  for (int i=0; i<mParentPlot->plottableCount(); ++i)
20373  {
20374  if (QCPColorMap *cm = qobject_cast<QCPColorMap*>(mParentPlot->plottable(i)))
20375  if (cm->colorScale() == this)
20376  result.append(cm);
20377  }
20378  return result;
20379 }
20380 
20387 void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps)
20388 {
20389  QList<QCPColorMap*> maps = colorMaps();
20390  QCPRange newRange;
20391  bool haveRange = false;
20395  foreach (QCPColorMap *map, maps)
20396  {
20397  if (!map->realVisibility() && onlyVisibleMaps)
20398  continue;
20399  QCPRange mapRange;
20400  if (map->colorScale() == this)
20401  {
20402  bool currentFoundRange = true;
20403  mapRange = map->data()->dataBounds();
20404  if (sign == QCP::sdPositive)
20405  {
20406  if (mapRange.lower <= 0 && mapRange.upper > 0)
20407  mapRange.lower = mapRange.upper*1e-3;
20408  else if (mapRange.lower <= 0 && mapRange.upper <= 0)
20409  currentFoundRange = false;
20410  } else if (sign == QCP::sdNegative)
20411  {
20412  if (mapRange.upper >= 0 && mapRange.lower < 0)
20413  mapRange.upper = mapRange.lower*1e-3;
20414  else if (mapRange.upper >= 0 && mapRange.lower >= 0)
20415  currentFoundRange = false;
20416  }
20417  if (currentFoundRange)
20418  {
20419  if (!haveRange)
20420  newRange = mapRange;
20421  else
20422  newRange.expand(mapRange);
20423  haveRange = true;
20424  }
20425  }
20426  }
20427  if (haveRange)
20428  {
20429  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data
20430  {
20431  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
20433  {
20434  newRange.lower = center-mDataRange.size()/2.0;
20435  newRange.upper = center+mDataRange.size()/2.0;
20436  } else // mScaleType == stLogarithmic
20437  {
20438  newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower);
20439  newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower);
20440  }
20441  }
20442  setDataRange(newRange);
20443  }
20444 }
20445 
20446 /* inherits documentation from base class */
20448 {
20449  QCPLayoutElement::update(phase);
20450  if (!mAxisRect)
20451  {
20452  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20453  return;
20454  }
20455 
20456  mAxisRect.data()->update(phase);
20457 
20458  switch (phase)
20459  {
20460  case upMargins:
20461  {
20463  {
20464  setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom());
20465  setMinimumSize(0, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom());
20466  } else
20467  {
20468  setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right(), QWIDGETSIZE_MAX);
20469  setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right(), 0);
20470  }
20471  break;
20472  }
20473  case upLayout:
20474  {
20475  mAxisRect.data()->setOuterRect(rect());
20476  break;
20477  }
20478  default: break;
20479  }
20480 }
20481 
20482 /* inherits documentation from base class */
20484 {
20485  painter->setAntialiasing(false);
20486 }
20487 
20488 /* inherits documentation from base class */
20489 void QCPColorScale::mousePressEvent(QMouseEvent *event, const QVariant &details)
20490 {
20491  if (!mAxisRect)
20492  {
20493  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20494  return;
20495  }
20496  mAxisRect.data()->mousePressEvent(event, details);
20497 }
20498 
20499 /* inherits documentation from base class */
20500 void QCPColorScale::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
20501 {
20502  if (!mAxisRect)
20503  {
20504  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20505  return;
20506  }
20507  mAxisRect.data()->mouseMoveEvent(event, startPos);
20508 }
20509 
20510 /* inherits documentation from base class */
20511 void QCPColorScale::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
20512 {
20513  if (!mAxisRect)
20514  {
20515  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20516  return;
20517  }
20518  mAxisRect.data()->mouseReleaseEvent(event, startPos);
20519 }
20520 
20521 /* inherits documentation from base class */
20522 void QCPColorScale::wheelEvent(QWheelEvent *event)
20523 {
20524  if (!mAxisRect)
20525  {
20526  qDebug() << Q_FUNC_INFO << "internal axis rect was deleted";
20527  return;
20528  }
20529  mAxisRect.data()->wheelEvent(event);
20530 }
20531 
20535 
20551  QCPAxisRect(parentColorScale->parentPlot(), true),
20552  mParentColorScale(parentColorScale),
20553  mGradientImageInvalidated(true)
20554 {
20555  setParentLayerable(parentColorScale);
20556  setMinimumMargins(QMargins(0, 0, 0, 0));
20557  const QList<QCPAxis::AxisType> allAxisTypes = QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight;
20558  foreach (QCPAxis::AxisType type, allAxisTypes)
20559  {
20560  axis(type)->setVisible(true);
20561  axis(type)->grid()->setVisible(false);
20562  axis(type)->setPadding(0);
20563  connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts)));
20564  connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts)));
20565  }
20566 
20567  connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange)));
20568  connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange)));
20569  connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange)));
20570  connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
20571  connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType)));
20572  connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType)));
20573  connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType)));
20574  connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType)));
20575 
20576  // make layer transfers of color scale transfer to axis rect and axes
20577  // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect:
20578  connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*)));
20579  foreach (QCPAxis::AxisType type, allAxisTypes)
20580  connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*)));
20581 }
20582 
20591 {
20594 
20595  bool mirrorHorz = false;
20596  bool mirrorVert = false;
20598  {
20599  mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop);
20600  mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight);
20601  }
20602 
20603  painter->drawImage(rect().adjusted(0, -1, 0, -1), mGradientImage.mirrored(mirrorHorz, mirrorVert));
20604  QCPAxisRect::draw(painter);
20605 }
20606 
20613 {
20614  if (rect().isEmpty())
20615  return;
20616 
20617  const QImage::Format format = QImage::Format_ARGB32_Premultiplied;
20619  int w, h;
20620  QVector<double> data(n);
20621  for (int i=0; i<n; ++i)
20622  data[i] = i;
20624  {
20625  w = n;
20626  h = rect().height();
20627  mGradientImage = QImage(w, h, format);
20628  QVector<QRgb*> pixels;
20629  for (int y=0; y<h; ++y)
20630  pixels.append(reinterpret_cast<QRgb*>(mGradientImage.scanLine(y)));
20631  mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n);
20632  for (int y=1; y<h; ++y)
20633  memcpy(pixels.at(y), pixels.first(), size_t(n)*sizeof(QRgb));
20634  } else
20635  {
20636  w = rect().width();
20637  h = n;
20638  mGradientImage = QImage(w, h, format);
20639  for (int y=0; y<h; ++y)
20640  {
20641  QRgb *pixels = reinterpret_cast<QRgb*>(mGradientImage.scanLine(y));
20642  const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1));
20643  for (int x=0; x<w; ++x)
20644  pixels[x] = lineColor;
20645  }
20646  }
20647  mGradientImageInvalidated = false;
20648 }
20649 
20655 void QCPColorScaleAxisRectPrivate::axisSelectionChanged(QCPAxis::SelectableParts selectedParts)
20656 {
20657  // axis bases of four axes shall always (de-)selected synchronously:
20658  const QList<QCPAxis::AxisType> allAxisTypes = QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight;
20659  foreach (QCPAxis::AxisType type, allAxisTypes)
20660  {
20661  if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
20662  if (senderAxis->axisType() == type)
20663  continue;
20664 
20665  if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
20666  {
20667  if (selectedParts.testFlag(QCPAxis::spAxis))
20668  axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis);
20669  else
20670  axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis);
20671  }
20672  }
20673 }
20674 
20680 void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts)
20681 {
20682  // synchronize axis base selectability:
20683  const QList<QCPAxis::AxisType> allAxisTypes = QList<QCPAxis::AxisType>() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight;
20684  foreach (QCPAxis::AxisType type, allAxisTypes)
20685  {
20686  if (QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
20687  if (senderAxis->axisType() == type)
20688  continue;
20689 
20690  if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis))
20691  {
20692  if (selectableParts.testFlag(QCPAxis::spAxis))
20693  axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis);
20694  else
20695  axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis);
20696  }
20697  }
20698 }
20699 /* end of 'src/layoutelements/layoutelement-colorscale.cpp' */
20700 
20701 
20702 /* including file 'src/plottables/plottable-graph.cpp' */
20703 /* modified 2021-03-29T02:30:44, size 74518 */
20704 
20708 
20723 /* start documentation of inline functions */
20724 
20774 /* end documentation of inline functions */
20775 
20780  key(0),
20781  value(0)
20782 {
20783 }
20784 
20788 QCPGraphData::QCPGraphData(double key, double value) :
20789  key(key),
20790  value(value)
20791 {
20792 }
20793 
20794 
20798 
20837 /* start of documentation of inline functions */
20838 
20846 /* end of documentation of inline functions */
20847 
20860 QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) :
20861  QCPAbstractPlottable1D<QCPGraphData>(keyAxis, valueAxis),
20862  mLineStyle{},
20863  mScatterSkip{},
20864  mAdaptiveSampling{}
20865 {
20866  // special handling for QCPGraphs to maintain the simple graph interface:
20867  mParentPlot->registerGraph(this);
20868 
20869  setPen(QPen(Qt::blue, 0));
20870  setBrush(Qt::NoBrush);
20871 
20872  setLineStyle(lsLine);
20873  setScatterSkip(0);
20874  setChannelFillGraph(nullptr);
20875  setAdaptiveSampling(true);
20876 }
20877 
20879 {
20880 }
20881 
20897 void QCPGraph::setData(QSharedPointer<QCPGraphDataContainer> data)
20898 {
20899  mDataContainer = data;
20900 }
20901 
20913 void QCPGraph::setData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
20914 {
20915  mDataContainer->clear();
20916  addData(keys, values, alreadySorted);
20917 }
20918 
20926 {
20927  mLineStyle = ls;
20928 }
20929 
20937 {
20938  mScatterStyle = style;
20939 }
20940 
20953 {
20954  mScatterSkip = qMax(0, skip);
20955 }
20956 
20967 {
20968  // prevent setting channel target to this graph itself:
20969  if (targetGraph == this)
20970  {
20971  qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself";
20972  mChannelFillGraph = nullptr;
20973  return;
20974  }
20975  // prevent setting channel target to a graph not in the plot:
20976  if (targetGraph && targetGraph->mParentPlot != mParentPlot)
20977  {
20978  qDebug() << Q_FUNC_INFO << "targetGraph not in same plot";
20979  mChannelFillGraph = nullptr;
20980  return;
20981  }
20982 
20983  mChannelFillGraph = targetGraph;
20984 }
20985 
21018 {
21019  mAdaptiveSampling = enabled;
21020 }
21021 
21034 void QCPGraph::addData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
21035 {
21036  if (keys.size() != values.size())
21037  qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size();
21038  const int n = qMin(keys.size(), values.size());
21039  QVector<QCPGraphData> tempData(n);
21040  QVector<QCPGraphData>::iterator it = tempData.begin();
21041  const QVector<QCPGraphData>::iterator itEnd = tempData.end();
21042  int i = 0;
21043  while (it != itEnd)
21044  {
21045  it->key = keys[i];
21046  it->value = values[i];
21047  ++it;
21048  ++i;
21049  }
21050  mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write
21051 }
21052 
21060 void QCPGraph::addData(double key, double value)
21061 {
21062  mDataContainer->add(QCPGraphData(key, value));
21063 }
21064 
21073 double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
21074 {
21075  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
21076  return -1;
21077  if (!mKeyAxis || !mValueAxis)
21078  return -1;
21079 
21080  if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
21081  {
21082  QCPGraphDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd();
21083  double result = pointDistance(pos, closestDataPoint);
21084  if (details)
21085  {
21086  int pointIndex = int(closestDataPoint-mDataContainer->constBegin());
21087  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
21088  }
21089  return result;
21090  } else
21091  return -1;
21092 }
21093 
21094 /* inherits documentation from base class */
21095 QCPRange QCPGraph::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
21096 {
21097  return mDataContainer->keyRange(foundRange, inSignDomain);
21098 }
21099 
21100 /* inherits documentation from base class */
21101 QCPRange QCPGraph::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
21102 {
21103  return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
21104 }
21105 
21106 /* inherits documentation from base class */
21108 {
21109  if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21110  if (mKeyAxis.data()->range().size() <= 0 || mDataContainer->isEmpty()) return;
21111  if (mLineStyle == lsNone && mScatterStyle.isNone()) return;
21112 
21113  QVector<QPointF> lines, scatters; // line and (if necessary) scatter pixel coordinates will be stored here while iterating over segments
21114 
21115  // loop over and draw segments of unselected/selected data:
21116  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
21117  getDataSegments(selectedSegments, unselectedSegments);
21118  allSegments << unselectedSegments << selectedSegments;
21119  for (int i=0; i<allSegments.size(); ++i)
21120  {
21121  bool isSelectedSegment = i >= unselectedSegments.size();
21122  // get line pixel points appropriate to line style:
21123  QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).adjusted(-1, 1); // unselected segments extend lines to bordering selected data point (safe to exceed total data bounds in first/last segment, getLines takes care)
21124  getLines(&lines, lineDataRange);
21125 
21126  // check data validity if flag set:
21127 #ifdef QCUSTOMPLOT_CHECK_DATA
21129  for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it)
21130  {
21131  if (QCP::isInvalidData(it->key, it->value))
21132  qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "invalid." << "Plottable name:" << name();
21133  }
21134 #endif
21135 
21136  // draw fill of graph:
21137  if (isSelectedSegment && mSelectionDecorator)
21138  mSelectionDecorator->applyBrush(painter);
21139  else
21140  painter->setBrush(mBrush);
21141  painter->setPen(Qt::NoPen);
21142  drawFill(painter, &lines);
21143 
21144  // draw line:
21145  if (mLineStyle != lsNone)
21146  {
21147  if (isSelectedSegment && mSelectionDecorator)
21148  mSelectionDecorator->applyPen(painter);
21149  else
21150  painter->setPen(mPen);
21151  painter->setBrush(Qt::NoBrush);
21152  if (mLineStyle == lsImpulse)
21153  drawImpulsePlot(painter, lines);
21154  else
21155  drawLinePlot(painter, lines); // also step plots can be drawn as a line plot
21156  }
21157 
21158  // draw scatters:
21159  QCPScatterStyle finalScatterStyle = mScatterStyle;
21160  if (isSelectedSegment && mSelectionDecorator)
21162  if (!finalScatterStyle.isNone())
21163  {
21164  getScatters(&scatters, allSegments.at(i));
21165  drawScatterPlot(painter, scatters, finalScatterStyle);
21166  }
21167  }
21168 
21169  // draw other selection decoration that isn't just line/scatter pens and brushes:
21170  if (mSelectionDecorator)
21172 }
21173 
21174 /* inherits documentation from base class */
21175 void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
21176 {
21177  // draw fill:
21178  if (mBrush.style() != Qt::NoBrush)
21179  {
21180  applyFillAntialiasingHint(painter);
21181  painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
21182  }
21183  // draw line vertically centered:
21184  if (mLineStyle != lsNone)
21185  {
21187  painter->setPen(mPen);
21188  painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
21189  }
21190  // draw scatter symbol:
21191  if (!mScatterStyle.isNone())
21192  {
21194  // scale scatter pixmap if it's too large to fit in legend icon rect:
21195  if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
21196  {
21197  QCPScatterStyle scaledStyle(mScatterStyle);
21198  scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
21199  scaledStyle.applyTo(painter, mPen);
21200  scaledStyle.drawShape(painter, QRectF(rect).center());
21201  } else
21202  {
21203  mScatterStyle.applyTo(painter, mPen);
21204  mScatterStyle.drawShape(painter, QRectF(rect).center());
21205  }
21206  }
21207 }
21208 
21229 void QCPGraph::getLines(QVector<QPointF> *lines, const QCPDataRange &dataRange) const
21230 {
21231  if (!lines) return;
21233  getVisibleDataBounds(begin, end, dataRange);
21234  if (begin == end)
21235  {
21236  lines->clear();
21237  return;
21238  }
21239 
21240  QVector<QCPGraphData> lineData;
21241  if (mLineStyle != lsNone)
21242  getOptimizedLineData(&lineData, begin, end);
21243 
21244  if (mKeyAxis->rangeReversed() != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending in lineData (significantly simplifies following processing)
21245  std::reverse(lineData.begin(), lineData.end());
21246 
21247  switch (mLineStyle)
21248  {
21249  case lsNone: lines->clear(); break;
21250  case lsLine: *lines = dataToLines(lineData); break;
21251  case lsStepLeft: *lines = dataToStepLeftLines(lineData); break;
21252  case lsStepRight: *lines = dataToStepRightLines(lineData); break;
21253  case lsStepCenter: *lines = dataToStepCenterLines(lineData); break;
21254  case lsImpulse: *lines = dataToImpulseLines(lineData); break;
21255  }
21256 }
21257 
21270 void QCPGraph::getScatters(QVector<QPointF> *scatters, const QCPDataRange &dataRange) const
21271 {
21272  if (!scatters) return;
21273  QCPAxis *keyAxis = mKeyAxis.data();
21274  QCPAxis *valueAxis = mValueAxis.data();
21275  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; scatters->clear(); return; }
21276 
21278  getVisibleDataBounds(begin, end, dataRange);
21279  if (begin == end)
21280  {
21281  scatters->clear();
21282  return;
21283  }
21284 
21285  QVector<QCPGraphData> data;
21286  getOptimizedScatterData(&data, begin, end);
21287 
21288  if (mKeyAxis->rangeReversed() != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending in data (significantly simplifies following processing)
21289  std::reverse(data.begin(), data.end());
21290 
21291  scatters->resize(data.size());
21292  if (keyAxis->orientation() == Qt::Vertical)
21293  {
21294  for (int i=0; i<data.size(); ++i)
21295  {
21296  if (!qIsNaN(data.at(i).value))
21297  {
21298  (*scatters)[i].setX(valueAxis->coordToPixel(data.at(i).value));
21299  (*scatters)[i].setY(keyAxis->coordToPixel(data.at(i).key));
21300  }
21301  }
21302  } else
21303  {
21304  for (int i=0; i<data.size(); ++i)
21305  {
21306  if (!qIsNaN(data.at(i).value))
21307  {
21308  (*scatters)[i].setX(keyAxis->coordToPixel(data.at(i).key));
21309  (*scatters)[i].setY(valueAxis->coordToPixel(data.at(i).value));
21310  }
21311  }
21312  }
21313 }
21314 
21325 QVector<QPointF> QCPGraph::dataToLines(const QVector<QCPGraphData> &data) const
21326 {
21327  QVector<QPointF> result;
21328  QCPAxis *keyAxis = mKeyAxis.data();
21329  QCPAxis *valueAxis = mValueAxis.data();
21330  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; }
21331 
21332  result.resize(data.size());
21333 
21334  // transform data points to pixels:
21335  if (keyAxis->orientation() == Qt::Vertical)
21336  {
21337  for (int i=0; i<data.size(); ++i)
21338  {
21339  result[i].setX(valueAxis->coordToPixel(data.at(i).value));
21340  result[i].setY(keyAxis->coordToPixel(data.at(i).key));
21341  }
21342  } else // key axis is horizontal
21343  {
21344  for (int i=0; i<data.size(); ++i)
21345  {
21346  result[i].setX(keyAxis->coordToPixel(data.at(i).key));
21347  result[i].setY(valueAxis->coordToPixel(data.at(i).value));
21348  }
21349  }
21350  return result;
21351 }
21352 
21363 QVector<QPointF> QCPGraph::dataToStepLeftLines(const QVector<QCPGraphData> &data) const
21364 {
21365  QVector<QPointF> result;
21366  QCPAxis *keyAxis = mKeyAxis.data();
21367  QCPAxis *valueAxis = mValueAxis.data();
21368  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; }
21369 
21370  result.resize(data.size()*2);
21371 
21372  // calculate steps from data and transform to pixel coordinates:
21373  if (keyAxis->orientation() == Qt::Vertical)
21374  {
21375  double lastValue = valueAxis->coordToPixel(data.first().value);
21376  for (int i=0; i<data.size(); ++i)
21377  {
21378  const double key = keyAxis->coordToPixel(data.at(i).key);
21379  result[i*2+0].setX(lastValue);
21380  result[i*2+0].setY(key);
21381  lastValue = valueAxis->coordToPixel(data.at(i).value);
21382  result[i*2+1].setX(lastValue);
21383  result[i*2+1].setY(key);
21384  }
21385  } else // key axis is horizontal
21386  {
21387  double lastValue = valueAxis->coordToPixel(data.first().value);
21388  for (int i=0; i<data.size(); ++i)
21389  {
21390  const double key = keyAxis->coordToPixel(data.at(i).key);
21391  result[i*2+0].setX(key);
21392  result[i*2+0].setY(lastValue);
21393  lastValue = valueAxis->coordToPixel(data.at(i).value);
21394  result[i*2+1].setX(key);
21395  result[i*2+1].setY(lastValue);
21396  }
21397  }
21398  return result;
21399 }
21400 
21411 QVector<QPointF> QCPGraph::dataToStepRightLines(const QVector<QCPGraphData> &data) const
21412 {
21413  QVector<QPointF> result;
21414  QCPAxis *keyAxis = mKeyAxis.data();
21415  QCPAxis *valueAxis = mValueAxis.data();
21416  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; }
21417 
21418  result.resize(data.size()*2);
21419 
21420  // calculate steps from data and transform to pixel coordinates:
21421  if (keyAxis->orientation() == Qt::Vertical)
21422  {
21423  double lastKey = keyAxis->coordToPixel(data.first().key);
21424  for (int i=0; i<data.size(); ++i)
21425  {
21426  const double value = valueAxis->coordToPixel(data.at(i).value);
21427  result[i*2+0].setX(value);
21428  result[i*2+0].setY(lastKey);
21429  lastKey = keyAxis->coordToPixel(data.at(i).key);
21430  result[i*2+1].setX(value);
21431  result[i*2+1].setY(lastKey);
21432  }
21433  } else // key axis is horizontal
21434  {
21435  double lastKey = keyAxis->coordToPixel(data.first().key);
21436  for (int i=0; i<data.size(); ++i)
21437  {
21438  const double value = valueAxis->coordToPixel(data.at(i).value);
21439  result[i*2+0].setX(lastKey);
21440  result[i*2+0].setY(value);
21441  lastKey = keyAxis->coordToPixel(data.at(i).key);
21442  result[i*2+1].setX(lastKey);
21443  result[i*2+1].setY(value);
21444  }
21445  }
21446  return result;
21447 }
21448 
21459 QVector<QPointF> QCPGraph::dataToStepCenterLines(const QVector<QCPGraphData> &data) const
21460 {
21461  QVector<QPointF> result;
21462  QCPAxis *keyAxis = mKeyAxis.data();
21463  QCPAxis *valueAxis = mValueAxis.data();
21464  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; }
21465 
21466  result.resize(data.size()*2);
21467 
21468  // calculate steps from data and transform to pixel coordinates:
21469  if (keyAxis->orientation() == Qt::Vertical)
21470  {
21471  double lastKey = keyAxis->coordToPixel(data.first().key);
21472  double lastValue = valueAxis->coordToPixel(data.first().value);
21473  result[0].setX(lastValue);
21474  result[0].setY(lastKey);
21475  for (int i=1; i<data.size(); ++i)
21476  {
21477  const double key = (keyAxis->coordToPixel(data.at(i).key)+lastKey)*0.5;
21478  result[i*2-1].setX(lastValue);
21479  result[i*2-1].setY(key);
21480  lastValue = valueAxis->coordToPixel(data.at(i).value);
21481  lastKey = keyAxis->coordToPixel(data.at(i).key);
21482  result[i*2+0].setX(lastValue);
21483  result[i*2+0].setY(key);
21484  }
21485  result[data.size()*2-1].setX(lastValue);
21486  result[data.size()*2-1].setY(lastKey);
21487  } else // key axis is horizontal
21488  {
21489  double lastKey = keyAxis->coordToPixel(data.first().key);
21490  double lastValue = valueAxis->coordToPixel(data.first().value);
21491  result[0].setX(lastKey);
21492  result[0].setY(lastValue);
21493  for (int i=1; i<data.size(); ++i)
21494  {
21495  const double key = (keyAxis->coordToPixel(data.at(i).key)+lastKey)*0.5;
21496  result[i*2-1].setX(key);
21497  result[i*2-1].setY(lastValue);
21498  lastValue = valueAxis->coordToPixel(data.at(i).value);
21499  lastKey = keyAxis->coordToPixel(data.at(i).key);
21500  result[i*2+0].setX(key);
21501  result[i*2+0].setY(lastValue);
21502  }
21503  result[data.size()*2-1].setX(lastKey);
21504  result[data.size()*2-1].setY(lastValue);
21505  }
21506  return result;
21507 }
21508 
21519 QVector<QPointF> QCPGraph::dataToImpulseLines(const QVector<QCPGraphData> &data) const
21520 {
21521  QVector<QPointF> result;
21522  QCPAxis *keyAxis = mKeyAxis.data();
21523  QCPAxis *valueAxis = mValueAxis.data();
21524  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; }
21525 
21526  result.resize(data.size()*2);
21527 
21528  // transform data points to pixels:
21529  if (keyAxis->orientation() == Qt::Vertical)
21530  {
21531  for (int i=0; i<data.size(); ++i)
21532  {
21533  const double key = keyAxis->coordToPixel(data.at(i).key);
21534  result[i*2+0].setX(valueAxis->coordToPixel(0));
21535  result[i*2+0].setY(key);
21536  result[i*2+1].setX(valueAxis->coordToPixel(data.at(i).value));
21537  result[i*2+1].setY(key);
21538  }
21539  } else // key axis is horizontal
21540  {
21541  for (int i=0; i<data.size(); ++i)
21542  {
21543  const double key = keyAxis->coordToPixel(data.at(i).key);
21544  result[i*2+0].setX(key);
21545  result[i*2+0].setY(valueAxis->coordToPixel(0));
21546  result[i*2+1].setX(key);
21547  result[i*2+1].setY(valueAxis->coordToPixel(data.at(i).value));
21548  }
21549  }
21550  return result;
21551 }
21552 
21570 void QCPGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lines) const
21571 {
21572  if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot
21573  if (painter->brush().style() == Qt::NoBrush || painter->brush().color().alpha() == 0) return;
21574 
21575  applyFillAntialiasingHint(painter);
21576  const QVector<QCPDataRange> segments = getNonNanSegments(lines, keyAxis()->orientation());
21577  if (!mChannelFillGraph)
21578  {
21579  // draw base fill under graph, fill goes all the way to the zero-value-line:
21580  foreach (QCPDataRange segment, segments)
21581  painter->drawPolygon(getFillPolygon(lines, segment));
21582  } else
21583  {
21584  // draw fill between this graph and mChannelFillGraph:
21585  QVector<QPointF> otherLines;
21586  mChannelFillGraph->getLines(&otherLines, QCPDataRange(0, mChannelFillGraph->dataCount()));
21587  if (!otherLines.isEmpty())
21588  {
21589  QVector<QCPDataRange> otherSegments = getNonNanSegments(&otherLines, mChannelFillGraph->keyAxis()->orientation());
21590  QVector<QPair<QCPDataRange, QCPDataRange> > segmentPairs = getOverlappingSegments(segments, lines, otherSegments, &otherLines);
21591  for (int i=0; i<segmentPairs.size(); ++i)
21592  painter->drawPolygon(getChannelFillPolygon(lines, segmentPairs.at(i).first, &otherLines, segmentPairs.at(i).second));
21593  }
21594  }
21595 }
21596 
21604 void QCPGraph::drawScatterPlot(QCPPainter *painter, const QVector<QPointF> &scatters, const QCPScatterStyle &style) const
21605 {
21607  style.applyTo(painter, mPen);
21608  foreach (const QPointF &scatter, scatters)
21609  style.drawShape(painter, scatter.x(), scatter.y());
21610 }
21611 
21618 void QCPGraph::drawLinePlot(QCPPainter *painter, const QVector<QPointF> &lines) const
21619 {
21620  if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
21621  {
21623  drawPolyline(painter, lines);
21624  }
21625 }
21626 
21635 void QCPGraph::drawImpulsePlot(QCPPainter *painter, const QVector<QPointF> &lines) const
21636 {
21637  if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
21638  {
21640  QPen oldPen = painter->pen();
21641  QPen newPen = painter->pen();
21642  newPen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line
21643  painter->setPen(newPen);
21644  painter->drawLines(lines);
21645  painter->setPen(oldPen);
21646  }
21647 }
21648 
21661 void QCPGraph::getOptimizedLineData(QVector<QCPGraphData> *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const
21662 {
21663  if (!lineData) return;
21664  QCPAxis *keyAxis = mKeyAxis.data();
21665  QCPAxis *valueAxis = mValueAxis.data();
21666  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21667  if (begin == end) return;
21668 
21669  int dataCount = int(end-begin);
21670  int maxCount = (std::numeric_limits<int>::max)();
21671  if (mAdaptiveSampling)
21672  {
21673  double keyPixelSpan = qAbs(keyAxis->coordToPixel(begin->key)-keyAxis->coordToPixel((end-1)->key));
21674  if (2*keyPixelSpan+2 < static_cast<double>((std::numeric_limits<int>::max)()))
21675  maxCount = int(2*keyPixelSpan+2);
21676  }
21677 
21678  if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
21679  {
21681  double minValue = it->value;
21682  double maxValue = it->value;
21683  QCPGraphDataContainer::const_iterator currentIntervalFirstPoint = it;
21684  int reversedFactor = keyAxis->pixelOrientation(); // is used to calculate keyEpsilon pixel into the correct direction
21685  int reversedRound = reversedFactor==-1 ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
21686  double currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(begin->key)+reversedRound));
21687  double lastIntervalEndKey = currentIntervalStartKey;
21688  double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
21689  bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
21690  int intervalDataCount = 1;
21691  ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect
21692  while (it != end)
21693  {
21694  if (it->key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary
21695  {
21696  if (it->value < minValue)
21697  minValue = it->value;
21698  else if (it->value > maxValue)
21699  maxValue = it->value;
21700  ++intervalDataCount;
21701  } else // new pixel interval started
21702  {
21703  if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
21704  {
21705  if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point
21706  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint->value));
21707  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
21708  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
21709  if (it->key > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point
21710  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.8, (it-1)->value));
21711  } else
21712  lineData->append(QCPGraphData(currentIntervalFirstPoint->key, currentIntervalFirstPoint->value));
21713  lastIntervalEndKey = (it-1)->key;
21714  minValue = it->value;
21715  maxValue = it->value;
21716  currentIntervalFirstPoint = it;
21717  currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(it->key)+reversedRound));
21718  if (keyEpsilonVariable)
21719  keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
21720  intervalDataCount = 1;
21721  }
21722  ++it;
21723  }
21724  // handle last interval:
21725  if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster
21726  {
21727  if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point
21728  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint->value));
21729  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
21730  lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
21731  } else
21732  lineData->append(QCPGraphData(currentIntervalFirstPoint->key, currentIntervalFirstPoint->value));
21733 
21734  } else // don't use adaptive sampling algorithm, transfer points one-to-one from the data container into the output
21735  {
21736  lineData->resize(dataCount);
21737  std::copy(begin, end, lineData->begin());
21738  }
21739 }
21740 
21754 {
21755  if (!scatterData) return;
21756  QCPAxis *keyAxis = mKeyAxis.data();
21757  QCPAxis *valueAxis = mValueAxis.data();
21758  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21759 
21760  const int scatterModulo = mScatterSkip+1;
21761  const bool doScatterSkip = mScatterSkip > 0;
21762  int beginIndex = int(begin-mDataContainer->constBegin());
21763  int endIndex = int(end-mDataContainer->constBegin());
21764  while (doScatterSkip && begin != end && beginIndex % scatterModulo != 0) // advance begin iterator to first non-skipped scatter
21765  {
21766  ++beginIndex;
21767  ++begin;
21768  }
21769  if (begin == end) return;
21770  int dataCount = int(end-begin);
21771  int maxCount = (std::numeric_limits<int>::max)();
21772  if (mAdaptiveSampling)
21773  {
21774  int keyPixelSpan = int(qAbs(keyAxis->coordToPixel(begin->key)-keyAxis->coordToPixel((end-1)->key)));
21775  maxCount = 2*keyPixelSpan+2;
21776  }
21777 
21778  if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average
21779  {
21780  double valueMaxRange = valueAxis->range().upper;
21781  double valueMinRange = valueAxis->range().lower;
21783  int itIndex = int(beginIndex);
21784  double minValue = it->value;
21785  double maxValue = it->value;
21786  QCPGraphDataContainer::const_iterator minValueIt = it;
21787  QCPGraphDataContainer::const_iterator maxValueIt = it;
21788  QCPGraphDataContainer::const_iterator currentIntervalStart = it;
21789  int reversedFactor = keyAxis->pixelOrientation(); // is used to calculate keyEpsilon pixel into the correct direction
21790  int reversedRound = reversedFactor==-1 ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey
21791  double currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(begin->key)+reversedRound));
21792  double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates
21793  bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes)
21794  int intervalDataCount = 1;
21795  // advance iterator to second (non-skipped) data point because adaptive sampling works in 1 point retrospect:
21796  if (!doScatterSkip)
21797  ++it;
21798  else
21799  {
21800  itIndex += scatterModulo;
21801  if (itIndex < endIndex) // make sure we didn't jump over end
21802  it += scatterModulo;
21803  else
21804  {
21805  it = end;
21806  itIndex = endIndex;
21807  }
21808  }
21809  // main loop over data points:
21810  while (it != end)
21811  {
21812  if (it->key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary
21813  {
21814  if (it->value < minValue && it->value > valueMinRange && it->value < valueMaxRange)
21815  {
21816  minValue = it->value;
21817  minValueIt = it;
21818  } else if (it->value > maxValue && it->value > valueMinRange && it->value < valueMaxRange)
21819  {
21820  maxValue = it->value;
21821  maxValueIt = it;
21822  }
21823  ++intervalDataCount;
21824  } else // new pixel started
21825  {
21826  if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
21827  {
21828  // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
21829  double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
21830  int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
21831  QCPGraphDataContainer::const_iterator intervalIt = currentIntervalStart;
21832  int c = 0;
21833  while (intervalIt != it)
21834  {
21835  if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt->value > valueMinRange && intervalIt->value < valueMaxRange)
21836  scatterData->append(*intervalIt);
21837  ++c;
21838  if (!doScatterSkip)
21839  ++intervalIt;
21840  else
21841  intervalIt += scatterModulo; // since we know indices of "currentIntervalStart", "intervalIt" and "it" are multiples of scatterModulo, we can't accidentally jump over "it" here
21842  }
21843  } else if (currentIntervalStart->value > valueMinRange && currentIntervalStart->value < valueMaxRange)
21844  scatterData->append(*currentIntervalStart);
21845  minValue = it->value;
21846  maxValue = it->value;
21847  currentIntervalStart = it;
21848  currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(it->key)+reversedRound));
21849  if (keyEpsilonVariable)
21850  keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
21851  intervalDataCount = 1;
21852  }
21853  // advance to next data point:
21854  if (!doScatterSkip)
21855  ++it;
21856  else
21857  {
21858  itIndex += scatterModulo;
21859  if (itIndex < endIndex) // make sure we didn't jump over end
21860  it += scatterModulo;
21861  else
21862  {
21863  it = end;
21864  itIndex = endIndex;
21865  }
21866  }
21867  }
21868  // handle last interval:
21869  if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them
21870  {
21871  // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot):
21872  double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue));
21873  int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average
21874  QCPGraphDataContainer::const_iterator intervalIt = currentIntervalStart;
21875  int intervalItIndex = int(intervalIt-mDataContainer->constBegin());
21876  int c = 0;
21877  while (intervalIt != it)
21878  {
21879  if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt->value > valueMinRange && intervalIt->value < valueMaxRange)
21880  scatterData->append(*intervalIt);
21881  ++c;
21882  if (!doScatterSkip)
21883  ++intervalIt;
21884  else // here we can't guarantee that adding scatterModulo doesn't exceed "it" (because "it" is equal to "end" here, and "end" isn't scatterModulo-aligned), so check via index comparison:
21885  {
21886  intervalItIndex += scatterModulo;
21887  if (intervalItIndex < itIndex)
21888  intervalIt += scatterModulo;
21889  else
21890  {
21891  intervalIt = it;
21892  intervalItIndex = itIndex;
21893  }
21894  }
21895  }
21896  } else if (currentIntervalStart->value > valueMinRange && currentIntervalStart->value < valueMaxRange)
21897  scatterData->append(*currentIntervalStart);
21898 
21899  } else // don't use adaptive sampling algorithm, transfer points one-to-one from the data container into the output
21900  {
21902  int itIndex = beginIndex;
21903  scatterData->reserve(dataCount);
21904  while (it != end)
21905  {
21906  scatterData->append(*it);
21907  // advance to next data point:
21908  if (!doScatterSkip)
21909  ++it;
21910  else
21911  {
21912  itIndex += scatterModulo;
21913  if (itIndex < endIndex)
21914  it += scatterModulo;
21915  else
21916  {
21917  it = end;
21918  itIndex = endIndex;
21919  }
21920  }
21921  }
21922  }
21923 }
21924 
21935 {
21936  if (rangeRestriction.isEmpty())
21937  {
21938  end = mDataContainer->constEnd();
21939  begin = end;
21940  } else
21941  {
21942  QCPAxis *keyAxis = mKeyAxis.data();
21943  QCPAxis *valueAxis = mValueAxis.data();
21944  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
21945  // get visible data range:
21946  begin = mDataContainer->findBegin(keyAxis->range().lower);
21947  end = mDataContainer->findEnd(keyAxis->range().upper);
21948  // limit lower/upperEnd to rangeRestriction:
21949  mDataContainer->limitIteratorsToDataRange(begin, end, rangeRestriction); // this also ensures rangeRestriction outside data bounds doesn't break anything
21950  }
21951 }
21952 
21964 QVector<QCPDataRange> QCPGraph::getNonNanSegments(const QVector<QPointF> *lineData, Qt::Orientation keyOrientation) const
21965 {
21966  QVector<QCPDataRange> result;
21967  const int n = lineData->size();
21968 
21969  QCPDataRange currentSegment(-1, -1);
21970  int i = 0;
21971 
21972  if (keyOrientation == Qt::Horizontal)
21973  {
21974  while (i < n)
21975  {
21976  while (i < n && qIsNaN(lineData->at(i).y())) // seek next non-NaN data point
21977  ++i;
21978  if (i == n)
21979  break;
21980  currentSegment.setBegin(i++);
21981  while (i < n && !qIsNaN(lineData->at(i).y())) // seek next NaN data point or end of data
21982  ++i;
21983  currentSegment.setEnd(i++);
21984  result.append(currentSegment);
21985  }
21986  } else // keyOrientation == Qt::Vertical
21987  {
21988  while (i < n)
21989  {
21990  while (i < n && qIsNaN(lineData->at(i).x())) // seek next non-NaN data point
21991  ++i;
21992  if (i == n)
21993  break;
21994  currentSegment.setBegin(i++);
21995  while (i < n && !qIsNaN(lineData->at(i).x())) // seek next NaN data point or end of data
21996  ++i;
21997  currentSegment.setEnd(i++);
21998  result.append(currentSegment);
21999  }
22000  }
22001  return result;
22002 }
22003 
22022 QVector<QPair<QCPDataRange, QCPDataRange> > QCPGraph::getOverlappingSegments(QVector<QCPDataRange> thisSegments, const QVector<QPointF> *thisData, QVector<QCPDataRange> otherSegments, const QVector<QPointF> *otherData) const
22023 {
22024  QVector<QPair<QCPDataRange, QCPDataRange> > result;
22025  if (thisData->isEmpty() || otherData->isEmpty() || thisSegments.isEmpty() || otherSegments.isEmpty())
22026  return result;
22027 
22028  int thisIndex = 0;
22029  int otherIndex = 0;
22030  const bool verticalKey = mKeyAxis->orientation() == Qt::Vertical;
22031  while (thisIndex < thisSegments.size() && otherIndex < otherSegments.size())
22032  {
22033  if (thisSegments.at(thisIndex).size() < 2) // segments with fewer than two points won't have a fill anyhow
22034  {
22035  ++thisIndex;
22036  continue;
22037  }
22038  if (otherSegments.at(otherIndex).size() < 2) // segments with fewer than two points won't have a fill anyhow
22039  {
22040  ++otherIndex;
22041  continue;
22042  }
22043  double thisLower, thisUpper, otherLower, otherUpper;
22044  if (!verticalKey)
22045  {
22046  thisLower = thisData->at(thisSegments.at(thisIndex).begin()).x();
22047  thisUpper = thisData->at(thisSegments.at(thisIndex).end()-1).x();
22048  otherLower = otherData->at(otherSegments.at(otherIndex).begin()).x();
22049  otherUpper = otherData->at(otherSegments.at(otherIndex).end()-1).x();
22050  } else
22051  {
22052  thisLower = thisData->at(thisSegments.at(thisIndex).begin()).y();
22053  thisUpper = thisData->at(thisSegments.at(thisIndex).end()-1).y();
22054  otherLower = otherData->at(otherSegments.at(otherIndex).begin()).y();
22055  otherUpper = otherData->at(otherSegments.at(otherIndex).end()-1).y();
22056  }
22057 
22058  int bPrecedence;
22059  if (segmentsIntersect(thisLower, thisUpper, otherLower, otherUpper, bPrecedence))
22060  result.append(QPair<QCPDataRange, QCPDataRange>(thisSegments.at(thisIndex), otherSegments.at(otherIndex)));
22061 
22062  if (bPrecedence <= 0) // otherSegment doesn't reach as far as thisSegment, so continue with next otherSegment, keeping current thisSegment
22063  ++otherIndex;
22064  else // otherSegment reaches further than thisSegment, so continue with next thisSegment, keeping current otherSegment
22065  ++thisIndex;
22066  }
22067 
22068  return result;
22069 }
22070 
22085 bool QCPGraph::segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, int &bPrecedence) const
22086 {
22087  bPrecedence = 0;
22088  if (aLower > bUpper)
22089  {
22090  bPrecedence = -1;
22091  return false;
22092  } else if (bLower > aUpper)
22093  {
22094  bPrecedence = 1;
22095  return false;
22096  } else
22097  {
22098  if (aUpper > bUpper)
22099  bPrecedence = -1;
22100  else if (aUpper < bUpper)
22101  bPrecedence = 1;
22102 
22103  return true;
22104  }
22105 }
22106 
22118 QPointF QCPGraph::getFillBasePoint(QPointF matchingDataPoint) const
22119 {
22120  QCPAxis *keyAxis = mKeyAxis.data();
22121  QCPAxis *valueAxis = mValueAxis.data();
22122  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; }
22123 
22124  QPointF result;
22126  {
22127  if (keyAxis->orientation() == Qt::Horizontal)
22128  {
22129  result.setX(matchingDataPoint.x());
22130  result.setY(valueAxis->coordToPixel(0));
22131  } else // keyAxis->orientation() == Qt::Vertical
22132  {
22133  result.setX(valueAxis->coordToPixel(0));
22134  result.setY(matchingDataPoint.y());
22135  }
22136  } else // valueAxis->mScaleType == QCPAxis::stLogarithmic
22137  {
22138  // In logarithmic scaling we can't just draw to value 0 so we just fill all the way
22139  // to the axis which is in the direction towards 0
22140  if (keyAxis->orientation() == Qt::Vertical)
22141  {
22142  if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
22143  (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
22144  result.setX(keyAxis->axisRect()->right());
22145  else
22146  result.setX(keyAxis->axisRect()->left());
22147  result.setY(matchingDataPoint.y());
22149  {
22150  result.setX(matchingDataPoint.x());
22151  if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) ||
22152  (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis
22153  result.setY(keyAxis->axisRect()->top());
22154  else
22155  result.setY(keyAxis->axisRect()->bottom());
22156  }
22157  }
22158  return result;
22159 }
22160 
22177 const QPolygonF QCPGraph::getFillPolygon(const QVector<QPointF> *lineData, QCPDataRange segment) const
22178 {
22179  if (segment.size() < 2)
22180  return QPolygonF();
22181  QPolygonF result(segment.size()+2);
22182 
22183  result[0] = getFillBasePoint(lineData->at(segment.begin()));
22184  std::copy(lineData->constBegin()+segment.begin(), lineData->constBegin()+segment.end(), result.begin()+1);
22185  result[result.size()-1] = getFillBasePoint(lineData->at(segment.end()-1));
22186 
22187  return result;
22188 }
22189 
22208 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData, QCPDataRange thisSegment, const QVector<QPointF> *otherData, QCPDataRange otherSegment) const
22209 {
22210  if (!mChannelFillGraph)
22211  return QPolygonF();
22212 
22213  QCPAxis *keyAxis = mKeyAxis.data();
22214  QCPAxis *valueAxis = mValueAxis.data();
22215  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); }
22216  if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); }
22217 
22218  if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation())
22219  return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis)
22220 
22221  if (thisData->isEmpty()) return QPolygonF();
22222  QVector<QPointF> thisSegmentData(thisSegment.size());
22223  QVector<QPointF> otherSegmentData(otherSegment.size());
22224  std::copy(thisData->constBegin()+thisSegment.begin(), thisData->constBegin()+thisSegment.end(), thisSegmentData.begin());
22225  std::copy(otherData->constBegin()+otherSegment.begin(), otherData->constBegin()+otherSegment.end(), otherSegmentData.begin());
22226  // pointers to be able to swap them, depending which data range needs cropping:
22227  QVector<QPointF> *staticData = &thisSegmentData;
22228  QVector<QPointF> *croppedData = &otherSegmentData;
22229 
22230  // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType):
22231  if (keyAxis->orientation() == Qt::Horizontal)
22232  {
22233  // x is key
22234  // crop lower bound:
22235  if (staticData->first().x() < croppedData->first().x()) // other one must be cropped
22236  qSwap(staticData, croppedData);
22237  const int lowBound = findIndexBelowX(croppedData, staticData->first().x());
22238  if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
22239  croppedData->remove(0, lowBound);
22240  // set lowest point of cropped data to fit exactly key position of first static data point via linear interpolation:
22241  if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
22242  double slope;
22243  if (!qFuzzyCompare(croppedData->at(1).x(), croppedData->at(0).x()))
22244  slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x());
22245  else
22246  slope = 0;
22247  (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x()));
22248  (*croppedData)[0].setX(staticData->first().x());
22249 
22250  // crop upper bound:
22251  if (staticData->last().x() > croppedData->last().x()) // other one must be cropped
22252  qSwap(staticData, croppedData);
22253  int highBound = findIndexAboveX(croppedData, staticData->last().x());
22254  if (highBound == -1) return QPolygonF(); // key ranges have no overlap
22255  croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
22256  // set highest point of cropped data to fit exactly key position of last static data point via linear interpolation:
22257  if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
22258  const int li = croppedData->size()-1; // last index
22259  if (!qFuzzyCompare(croppedData->at(li).x(), croppedData->at(li-1).x()))
22260  slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x());
22261  else
22262  slope = 0;
22263  (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x()));
22264  (*croppedData)[li].setX(staticData->last().x());
22265  } else // mKeyAxis->orientation() == Qt::Vertical
22266  {
22267  // y is key
22268  // crop lower bound:
22269  if (staticData->first().y() < croppedData->first().y()) // other one must be cropped
22270  qSwap(staticData, croppedData);
22271  int lowBound = findIndexBelowY(croppedData, staticData->first().y());
22272  if (lowBound == -1) return QPolygonF(); // key ranges have no overlap
22273  croppedData->remove(0, lowBound);
22274  // set lowest point of cropped data to fit exactly key position of first static data point via linear interpolation:
22275  if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
22276  double slope;
22277  if (!qFuzzyCompare(croppedData->at(1).y(), croppedData->at(0).y())) // avoid division by zero in step plots
22278  slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y());
22279  else
22280  slope = 0;
22281  (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y()));
22282  (*croppedData)[0].setY(staticData->first().y());
22283 
22284  // crop upper bound:
22285  if (staticData->last().y() > croppedData->last().y()) // other one must be cropped
22286  qSwap(staticData, croppedData);
22287  int highBound = findIndexAboveY(croppedData, staticData->last().y());
22288  if (highBound == -1) return QPolygonF(); // key ranges have no overlap
22289  croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
22290  // set highest point of cropped data to fit exactly key position of last static data point via linear interpolation:
22291  if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation
22292  int li = croppedData->size()-1; // last index
22293  if (!qFuzzyCompare(croppedData->at(li).y(), croppedData->at(li-1).y())) // avoid division by zero in step plots
22294  slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y());
22295  else
22296  slope = 0;
22297  (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y()));
22298  (*croppedData)[li].setY(staticData->last().y());
22299  }
22300 
22301  // return joined:
22302  for (int i=otherSegmentData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted
22303  thisSegmentData << otherSegmentData.at(i);
22304  return QPolygonF(thisSegmentData);
22305 }
22306 
22315 int QCPGraph::findIndexAboveX(const QVector<QPointF> *data, double x) const
22316 {
22317  for (int i=data->size()-1; i>=0; --i)
22318  {
22319  if (data->at(i).x() < x)
22320  {
22321  if (i<data->size()-1)
22322  return i+1;
22323  else
22324  return data->size()-1;
22325  }
22326  }
22327  return -1;
22328 }
22329 
22338 int QCPGraph::findIndexBelowX(const QVector<QPointF> *data, double x) const
22339 {
22340  for (int i=0; i<data->size(); ++i)
22341  {
22342  if (data->at(i).x() > x)
22343  {
22344  if (i>0)
22345  return i-1;
22346  else
22347  return 0;
22348  }
22349  }
22350  return -1;
22351 }
22352 
22361 int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const
22362 {
22363  for (int i=data->size()-1; i>=0; --i)
22364  {
22365  if (data->at(i).y() < y)
22366  {
22367  if (i<data->size()-1)
22368  return i+1;
22369  else
22370  return data->size()-1;
22371  }
22372  }
22373  return -1;
22374 }
22375 
22387 double QCPGraph::pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const
22388 {
22389  closestData = mDataContainer->constEnd();
22390  if (mDataContainer->isEmpty())
22391  return -1.0;
22392  if (mLineStyle == lsNone && mScatterStyle.isNone())
22393  return -1.0;
22394 
22395  // calculate minimum distances to graph data points and find closestData iterator:
22396  double minDistSqr = (std::numeric_limits<double>::max)();
22397  // determine which key range comes into question, taking selection tolerance around pos into account:
22398  double posKeyMin, posKeyMax, dummy;
22399  pixelsToCoords(pixelPoint-QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMin, dummy);
22400  pixelsToCoords(pixelPoint+QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMax, dummy);
22401  if (posKeyMin > posKeyMax)
22402  qSwap(posKeyMin, posKeyMax);
22403  // iterate over found data points and then choose the one with the shortest distance to pos:
22404  QCPGraphDataContainer::const_iterator begin = mDataContainer->findBegin(posKeyMin, true);
22405  QCPGraphDataContainer::const_iterator end = mDataContainer->findEnd(posKeyMax, true);
22406  for (QCPGraphDataContainer::const_iterator it=begin; it!=end; ++it)
22407  {
22408  const double currentDistSqr = QCPVector2D(coordsToPixels(it->key, it->value)-pixelPoint).lengthSquared();
22409  if (currentDistSqr < minDistSqr)
22410  {
22411  minDistSqr = currentDistSqr;
22412  closestData = it;
22413  }
22414  }
22415 
22416  // calculate distance to graph line if there is one (if so, will probably be smaller than distance to closest data point):
22417  if (mLineStyle != lsNone)
22418  {
22419  // line displayed, calculate distance to line segments:
22420  QVector<QPointF> lineData;
22421  getLines(&lineData, QCPDataRange(0, dataCount())); // don't limit data range further since with sharp data spikes, line segments may be closer to test point than segments with closer key coordinate
22422  QCPVector2D p(pixelPoint);
22423  const int step = mLineStyle==lsImpulse ? 2 : 1; // impulse plot differs from other line styles in that the lineData points are only pairwise connected
22424  for (int i=0; i<lineData.size()-1; i+=step)
22425  {
22426  const double currentDistSqr = p.distanceSquaredToLine(lineData.at(i), lineData.at(i+1));
22427  if (currentDistSqr < minDistSqr)
22428  minDistSqr = currentDistSqr;
22429  }
22430  }
22431 
22432  return qSqrt(minDistSqr);
22433 }
22434 
22443 int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const
22444 {
22445  for (int i=0; i<data->size(); ++i)
22446  {
22447  if (data->at(i).y() > y)
22448  {
22449  if (i>0)
22450  return i-1;
22451  else
22452  return 0;
22453  }
22454  }
22455  return -1;
22456 }
22457 /* end of 'src/plottables/plottable-graph.cpp' */
22458 
22459 
22460 /* including file 'src/plottables/plottable-curve.cpp' */
22461 /* modified 2021-03-29T02:30:44, size 63851 */
22462 
22466 
22482 /* start documentation of inline functions */
22483 
22534 /* end documentation of inline functions */
22535 
22540  t(0),
22541  key(0),
22542  value(0)
22543 {
22544 }
22545 
22549 QCPCurveData::QCPCurveData(double t, double key, double value) :
22550  t(t),
22551  key(key),
22552  value(value)
22553 {
22554 }
22555 
22556 
22560 
22597 /* start of documentation of inline functions */
22598 
22606 /* end of documentation of inline functions */
22607 
22618 QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) :
22619  QCPAbstractPlottable1D<QCPCurveData>(keyAxis, valueAxis),
22620  mScatterSkip{},
22621  mLineStyle{}
22622 {
22623  // modify inherited properties from abstract plottable:
22624  setPen(QPen(Qt::blue, 0));
22625  setBrush(Qt::NoBrush);
22626 
22627  setScatterStyle(QCPScatterStyle());
22628  setLineStyle(lsLine);
22629  setScatterSkip(0);
22630 }
22631 
22633 {
22634 }
22635 
22651 void QCPCurve::setData(QSharedPointer<QCPCurveDataContainer> data)
22652 {
22653  mDataContainer = data;
22654 }
22655 
22667 void QCPCurve::setData(const QVector<double> &t, const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
22668 {
22669  mDataContainer->clear();
22670  addData(t, keys, values, alreadySorted);
22671 }
22672 
22673 
22685 void QCPCurve::setData(const QVector<double> &keys, const QVector<double> &values)
22686 {
22687  mDataContainer->clear();
22688  addData(keys, values);
22689 }
22690 
22699 {
22700  mScatterStyle = style;
22701 }
22702 
22715 {
22716  mScatterSkip = qMax(0, skip);
22717 }
22718 
22727 {
22728  mLineStyle = style;
22729 }
22730 
22743 void QCPCurve::addData(const QVector<double> &t, const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
22744 {
22745  if (t.size() != keys.size() || t.size() != values.size())
22746  qDebug() << Q_FUNC_INFO << "ts, keys and values have different sizes:" << t.size() << keys.size() << values.size();
22747  const int n = qMin(qMin(t.size(), keys.size()), values.size());
22748  QVector<QCPCurveData> tempData(n);
22749  QVector<QCPCurveData>::iterator it = tempData.begin();
22750  const QVector<QCPCurveData>::iterator itEnd = tempData.end();
22751  int i = 0;
22752  while (it != itEnd)
22753  {
22754  it->t = t[i];
22755  it->key = keys[i];
22756  it->value = values[i];
22757  ++it;
22758  ++i;
22759  }
22760  mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write
22761 }
22762 
22775 void QCPCurve::addData(const QVector<double> &keys, const QVector<double> &values)
22776 {
22777  if (keys.size() != values.size())
22778  qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size();
22779  const int n = qMin(keys.size(), values.size());
22780  double tStart;
22781  if (!mDataContainer->isEmpty())
22782  tStart = (mDataContainer->constEnd()-1)->t + 1.0;
22783  else
22784  tStart = 0;
22785  QVector<QCPCurveData> tempData(n);
22786  QVector<QCPCurveData>::iterator it = tempData.begin();
22787  const QVector<QCPCurveData>::iterator itEnd = tempData.end();
22788  int i = 0;
22789  while (it != itEnd)
22790  {
22791  it->t = tStart + i;
22792  it->key = keys[i];
22793  it->value = values[i];
22794  ++it;
22795  ++i;
22796  }
22797  mDataContainer->add(tempData, true); // don't modify tempData beyond this to prevent copy on write
22798 }
22799 
22806 void QCPCurve::addData(double t, double key, double value)
22807 {
22808  mDataContainer->add(QCPCurveData(t, key, value));
22809 }
22810 
22821 void QCPCurve::addData(double key, double value)
22822 {
22823  if (!mDataContainer->isEmpty())
22824  mDataContainer->add(QCPCurveData((mDataContainer->constEnd()-1)->t + 1.0, key, value));
22825  else
22826  mDataContainer->add(QCPCurveData(0.0, key, value));
22827 }
22828 
22837 double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
22838 {
22839  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
22840  return -1;
22841  if (!mKeyAxis || !mValueAxis)
22842  return -1;
22843 
22844  if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
22845  {
22846  QCPCurveDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd();
22847  double result = pointDistance(pos, closestDataPoint);
22848  if (details)
22849  {
22850  int pointIndex = int( closestDataPoint-mDataContainer->constBegin() );
22851  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
22852  }
22853  return result;
22854  } else
22855  return -1;
22856 }
22857 
22858 /* inherits documentation from base class */
22859 QCPRange QCPCurve::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
22860 {
22861  return mDataContainer->keyRange(foundRange, inSignDomain);
22862 }
22863 
22864 /* inherits documentation from base class */
22865 QCPRange QCPCurve::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
22866 {
22867  return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
22868 }
22869 
22870 /* inherits documentation from base class */
22872 {
22873  if (mDataContainer->isEmpty()) return;
22874 
22875  // allocate line vector:
22876  QVector<QPointF> lines, scatters;
22877 
22878  // loop over and draw segments of unselected/selected data:
22879  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
22880  getDataSegments(selectedSegments, unselectedSegments);
22881  allSegments << unselectedSegments << selectedSegments;
22882  for (int i=0; i<allSegments.size(); ++i)
22883  {
22884  bool isSelectedSegment = i >= unselectedSegments.size();
22885 
22886  // fill with curve data:
22887  QPen finalCurvePen = mPen; // determine the final pen already here, because the line optimization depends on its stroke width
22888  if (isSelectedSegment && mSelectionDecorator)
22889  finalCurvePen = mSelectionDecorator->pen();
22890 
22891  QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).adjusted(-1, 1); // unselected segments extend lines to bordering selected data point (safe to exceed total data bounds in first/last segment, getCurveLines takes care)
22892  getCurveLines(&lines, lineDataRange, finalCurvePen.widthF());
22893 
22894  // check data validity if flag set:
22895  #ifdef QCUSTOMPLOT_CHECK_DATA
22896  for (QCPCurveDataContainer::const_iterator it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it)
22897  {
22898  if (QCP::isInvalidData(it->t) ||
22899  QCP::isInvalidData(it->key, it->value))
22900  qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "invalid." << "Plottable name:" << name();
22901  }
22902  #endif
22903 
22904  // draw curve fill:
22905  applyFillAntialiasingHint(painter);
22906  if (isSelectedSegment && mSelectionDecorator)
22907  mSelectionDecorator->applyBrush(painter);
22908  else
22909  painter->setBrush(mBrush);
22910  painter->setPen(Qt::NoPen);
22911  if (painter->brush().style() != Qt::NoBrush && painter->brush().color().alpha() != 0)
22912  painter->drawPolygon(QPolygonF(lines));
22913 
22914  // draw curve line:
22915  if (mLineStyle != lsNone)
22916  {
22917  painter->setPen(finalCurvePen);
22918  painter->setBrush(Qt::NoBrush);
22919  drawCurveLine(painter, lines);
22920  }
22921 
22922  // draw scatters:
22923  QCPScatterStyle finalScatterStyle = mScatterStyle;
22924  if (isSelectedSegment && mSelectionDecorator)
22926  if (!finalScatterStyle.isNone())
22927  {
22928  getScatters(&scatters, allSegments.at(i), finalScatterStyle.size());
22929  drawScatterPlot(painter, scatters, finalScatterStyle);
22930  }
22931  }
22932 
22933  // draw other selection decoration that isn't just line/scatter pens and brushes:
22934  if (mSelectionDecorator)
22936 }
22937 
22938 /* inherits documentation from base class */
22939 void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
22940 {
22941  // draw fill:
22942  if (mBrush.style() != Qt::NoBrush)
22943  {
22944  applyFillAntialiasingHint(painter);
22945  painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
22946  }
22947  // draw line vertically centered:
22948  if (mLineStyle != lsNone)
22949  {
22951  painter->setPen(mPen);
22952  painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
22953  }
22954  // draw scatter symbol:
22955  if (!mScatterStyle.isNone())
22956  {
22958  // scale scatter pixmap if it's too large to fit in legend icon rect:
22959  if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
22960  {
22961  QCPScatterStyle scaledStyle(mScatterStyle);
22962  scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
22963  scaledStyle.applyTo(painter, mPen);
22964  scaledStyle.drawShape(painter, QRectF(rect).center());
22965  } else
22966  {
22967  mScatterStyle.applyTo(painter, mPen);
22968  mScatterStyle.drawShape(painter, QRectF(rect).center());
22969  }
22970  }
22971 }
22972 
22979 void QCPCurve::drawCurveLine(QCPPainter *painter, const QVector<QPointF> &lines) const
22980 {
22981  if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
22982  {
22984  drawPolyline(painter, lines);
22985  }
22986 }
22987 
22995 void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector<QPointF> &points, const QCPScatterStyle &style) const
22996 {
22997  // draw scatter point symbols:
22999  style.applyTo(painter, mPen);
23000  foreach (const QPointF &point, points)
23001  if (!qIsNaN(point.x()) && !qIsNaN(point.y()))
23002  style.drawShape(painter, point);
23003 }
23004 
23033 void QCPCurve::getCurveLines(QVector<QPointF> *lines, const QCPDataRange &dataRange, double penWidth) const
23034 {
23035  if (!lines) return;
23036  lines->clear();
23037  QCPAxis *keyAxis = mKeyAxis.data();
23038  QCPAxis *valueAxis = mValueAxis.data();
23039  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
23040 
23041  // add margins to rect to compensate for stroke width
23042  const double strokeMargin = qMax(qreal(1.0), qreal(penWidth*0.75)); // stroke radius + 50% safety
23043  const double keyMin = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*keyAxis->pixelOrientation());
23044  const double keyMax = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*keyAxis->pixelOrientation());
23045  const double valueMin = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)-strokeMargin*valueAxis->pixelOrientation());
23046  const double valueMax = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)+strokeMargin*valueAxis->pixelOrientation());
23047  QCPCurveDataContainer::const_iterator itBegin = mDataContainer->constBegin();
23049  mDataContainer->limitIteratorsToDataRange(itBegin, itEnd, dataRange);
23050  if (itBegin == itEnd)
23051  return;
23053  QCPCurveDataContainer::const_iterator prevIt = itEnd-1;
23054  int prevRegion = getRegion(prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin);
23055  QVector<QPointF> trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right)
23056  while (it != itEnd)
23057  {
23058  const int currentRegion = getRegion(it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23059  if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R
23060  {
23061  if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal
23062  {
23063  QPointF crossA, crossB;
23064  if (prevRegion == 5) // we're coming from R, so add this point optimized
23065  {
23066  lines->append(getOptimizedPoint(currentRegion, it->key, it->value, prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin));
23067  // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point
23068  *lines << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23069  } else if (mayTraverse(prevRegion, currentRegion) &&
23070  getTraverse(prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin, crossA, crossB))
23071  {
23072  // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point:
23073  QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints;
23074  getTraverseCornerPoints(prevRegion, currentRegion, keyMin, valueMax, keyMax, valueMin, beforeTraverseCornerPoints, afterTraverseCornerPoints);
23075  if (it != itBegin)
23076  {
23077  *lines << beforeTraverseCornerPoints;
23078  lines->append(crossA);
23079  lines->append(crossB);
23080  *lines << afterTraverseCornerPoints;
23081  } else
23082  {
23083  lines->append(crossB);
23084  *lines << afterTraverseCornerPoints;
23085  trailingPoints << beforeTraverseCornerPoints << crossA ;
23086  }
23087  } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s)
23088  {
23089  *lines << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23090  }
23091  } else // segment does end in R, so we add previous point optimized and this point at original position
23092  {
23093  if (it == itBegin) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end
23094  trailingPoints << getOptimizedPoint(prevRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23095  else
23096  lines->append(getOptimizedPoint(prevRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin));
23097  lines->append(coordsToPixels(it->key, it->value));
23098  }
23099  } else // region didn't change
23100  {
23101  if (currentRegion == 5) // still in R, keep adding original points
23102  {
23103  lines->append(coordsToPixels(it->key, it->value));
23104  } else // still outside R, no need to add anything
23105  {
23106  // see how this is not doing anything? That's the main optimization...
23107  }
23108  }
23109  prevIt = it;
23110  prevRegion = currentRegion;
23111  ++it;
23112  }
23113  *lines << trailingPoints;
23114 }
23115 
23136 void QCPCurve::getScatters(QVector<QPointF> *scatters, const QCPDataRange &dataRange, double scatterWidth) const
23137 {
23138  if (!scatters) return;
23139  scatters->clear();
23140  QCPAxis *keyAxis = mKeyAxis.data();
23141  QCPAxis *valueAxis = mValueAxis.data();
23142  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
23143 
23146  mDataContainer->limitIteratorsToDataRange(begin, end, dataRange);
23147  if (begin == end)
23148  return;
23149  const int scatterModulo = mScatterSkip+1;
23150  const bool doScatterSkip = mScatterSkip > 0;
23151  int endIndex = int( end-mDataContainer->constBegin() );
23152 
23153  QCPRange keyRange = keyAxis->range();
23154  QCPRange valueRange = valueAxis->range();
23155  // extend range to include width of scatter symbols:
23156  keyRange.lower = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyRange.lower)-scatterWidth*keyAxis->pixelOrientation());
23157  keyRange.upper = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyRange.upper)+scatterWidth*keyAxis->pixelOrientation());
23158  valueRange.lower = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueRange.lower)-scatterWidth*valueAxis->pixelOrientation());
23159  valueRange.upper = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueRange.upper)+scatterWidth*valueAxis->pixelOrientation());
23160 
23162  int itIndex = int( begin-mDataContainer->constBegin() );
23163  while (doScatterSkip && it != end && itIndex % scatterModulo != 0) // advance begin iterator to first non-skipped scatter
23164  {
23165  ++itIndex;
23166  ++it;
23167  }
23168  if (keyAxis->orientation() == Qt::Vertical)
23169  {
23170  while (it != end)
23171  {
23172  if (!qIsNaN(it->value) && keyRange.contains(it->key) && valueRange.contains(it->value))
23173  scatters->append(QPointF(valueAxis->coordToPixel(it->value), keyAxis->coordToPixel(it->key)));
23174 
23175  // advance iterator to next (non-skipped) data point:
23176  if (!doScatterSkip)
23177  ++it;
23178  else
23179  {
23180  itIndex += scatterModulo;
23181  if (itIndex < endIndex) // make sure we didn't jump over end
23182  it += scatterModulo;
23183  else
23184  {
23185  it = end;
23186  itIndex = endIndex;
23187  }
23188  }
23189  }
23190  } else
23191  {
23192  while (it != end)
23193  {
23194  if (!qIsNaN(it->value) && keyRange.contains(it->key) && valueRange.contains(it->value))
23195  scatters->append(QPointF(keyAxis->coordToPixel(it->key), valueAxis->coordToPixel(it->value)));
23196 
23197  // advance iterator to next (non-skipped) data point:
23198  if (!doScatterSkip)
23199  ++it;
23200  else
23201  {
23202  itIndex += scatterModulo;
23203  if (itIndex < endIndex) // make sure we didn't jump over end
23204  it += scatterModulo;
23205  else
23206  {
23207  it = end;
23208  itIndex = endIndex;
23209  }
23210  }
23211  }
23212  }
23213 }
23214 
23234 int QCPCurve::getRegion(double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const
23235 {
23236  if (key < keyMin) // region 123
23237  {
23238  if (value > valueMax)
23239  return 1;
23240  else if (value < valueMin)
23241  return 3;
23242  else
23243  return 2;
23244  } else if (key > keyMax) // region 789
23245  {
23246  if (value > valueMax)
23247  return 7;
23248  else if (value < valueMin)
23249  return 9;
23250  else
23251  return 8;
23252  } else // region 456
23253  {
23254  if (value > valueMax)
23255  return 4;
23256  else if (value < valueMin)
23257  return 6;
23258  else
23259  return 5;
23260  }
23261 }
23262 
23278 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const
23279 {
23280  // The intersection point interpolation here is done in pixel coordinates, so we don't need to
23281  // differentiate between different axis scale types. Note that the nomenclature
23282  // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be
23283  // different in pixel coordinates (horz/vert key axes, reversed ranges)
23284 
23285  const double keyMinPx = mKeyAxis->coordToPixel(keyMin);
23286  const double keyMaxPx = mKeyAxis->coordToPixel(keyMax);
23287  const double valueMinPx = mValueAxis->coordToPixel(valueMin);
23288  const double valueMaxPx = mValueAxis->coordToPixel(valueMax);
23289  const double otherValuePx = mValueAxis->coordToPixel(otherValue);
23290  const double valuePx = mValueAxis->coordToPixel(value);
23291  const double otherKeyPx = mKeyAxis->coordToPixel(otherKey);
23292  const double keyPx = mKeyAxis->coordToPixel(key);
23293  double intersectKeyPx = keyMinPx; // initial key just a fail-safe
23294  double intersectValuePx = valueMinPx; // initial value just a fail-safe
23295  switch (otherRegion)
23296  {
23297  case 1: // top and left edge
23298  {
23299  intersectValuePx = valueMaxPx;
23300  intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23301  if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not intersected, then it must be left edge (qMin/qMax necessary since axes may be reversed)
23302  {
23303  intersectKeyPx = keyMinPx;
23304  intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23305  }
23306  break;
23307  }
23308  case 2: // left edge
23309  {
23310  intersectKeyPx = keyMinPx;
23311  intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23312  break;
23313  }
23314  case 3: // bottom and left edge
23315  {
23316  intersectValuePx = valueMinPx;
23317  intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23318  if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not intersected, then it must be left edge (qMin/qMax necessary since axes may be reversed)
23319  {
23320  intersectKeyPx = keyMinPx;
23321  intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23322  }
23323  break;
23324  }
23325  case 4: // top edge
23326  {
23327  intersectValuePx = valueMaxPx;
23328  intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23329  break;
23330  }
23331  case 5:
23332  {
23333  break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table
23334  }
23335  case 6: // bottom edge
23336  {
23337  intersectValuePx = valueMinPx;
23338  intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23339  break;
23340  }
23341  case 7: // top and right edge
23342  {
23343  intersectValuePx = valueMaxPx;
23344  intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23345  if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not intersected, then it must be right edge (qMin/qMax necessary since axes may be reversed)
23346  {
23347  intersectKeyPx = keyMaxPx;
23348  intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23349  }
23350  break;
23351  }
23352  case 8: // right edge
23353  {
23354  intersectKeyPx = keyMaxPx;
23355  intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23356  break;
23357  }
23358  case 9: // bottom and right edge
23359  {
23360  intersectValuePx = valueMinPx;
23361  intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23362  if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not intersected, then it must be right edge (qMin/qMax necessary since axes may be reversed)
23363  {
23364  intersectKeyPx = keyMaxPx;
23365  intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23366  }
23367  break;
23368  }
23369  }
23370  if (mKeyAxis->orientation() == Qt::Horizontal)
23371  return {intersectKeyPx, intersectValuePx};
23372  else
23373  return {intersectValuePx, intersectKeyPx};
23374 }
23375 
23394 QVector<QPointF> QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const
23395 {
23396  QVector<QPointF> result;
23397  switch (prevRegion)
23398  {
23399  case 1:
23400  {
23401  switch (currentRegion)
23402  {
23403  case 2: { result << coordsToPixels(keyMin, valueMax); break; }
23404  case 4: { result << coordsToPixels(keyMin, valueMax); break; }
23405  case 3: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMin, valueMin); break; }
23406  case 7: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMax, valueMax); break; }
23407  case 6: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; }
23408  case 8: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; }
23409  case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
23410  if ((value-prevValue)/(key-prevKey)*(keyMin-key)+value < valueMin) // segment passes below R
23411  { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); }
23412  else
23413  { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); }
23414  break;
23415  }
23416  }
23417  break;
23418  }
23419  case 2:
23420  {
23421  switch (currentRegion)
23422  {
23423  case 1: { result << coordsToPixels(keyMin, valueMax); break; }
23424  case 3: { result << coordsToPixels(keyMin, valueMin); break; }
23425  case 4: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; }
23426  case 6: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; }
23427  case 7: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); break; }
23428  case 9: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); break; }
23429  }
23430  break;
23431  }
23432  case 3:
23433  {
23434  switch (currentRegion)
23435  {
23436  case 2: { result << coordsToPixels(keyMin, valueMin); break; }
23437  case 6: { result << coordsToPixels(keyMin, valueMin); break; }
23438  case 1: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMin, valueMax); break; }
23439  case 9: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMax, valueMin); break; }
23440  case 4: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; }
23441  case 8: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; }
23442  case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
23443  if ((value-prevValue)/(key-prevKey)*(keyMax-key)+value < valueMin) // segment passes below R
23444  { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); }
23445  else
23446  { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); }
23447  break;
23448  }
23449  }
23450  break;
23451  }
23452  case 4:
23453  {
23454  switch (currentRegion)
23455  {
23456  case 1: { result << coordsToPixels(keyMin, valueMax); break; }
23457  case 7: { result << coordsToPixels(keyMax, valueMax); break; }
23458  case 2: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; }
23459  case 8: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; }
23460  case 3: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); break; }
23461  case 9: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); break; }
23462  }
23463  break;
23464  }
23465  case 5:
23466  {
23467  switch (currentRegion)
23468  {
23469  case 1: { result << coordsToPixels(keyMin, valueMax); break; }
23470  case 7: { result << coordsToPixels(keyMax, valueMax); break; }
23471  case 9: { result << coordsToPixels(keyMax, valueMin); break; }
23472  case 3: { result << coordsToPixels(keyMin, valueMin); break; }
23473  }
23474  break;
23475  }
23476  case 6:
23477  {
23478  switch (currentRegion)
23479  {
23480  case 3: { result << coordsToPixels(keyMin, valueMin); break; }
23481  case 9: { result << coordsToPixels(keyMax, valueMin); break; }
23482  case 2: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; }
23483  case 8: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; }
23484  case 1: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); break; }
23485  case 7: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); break; }
23486  }
23487  break;
23488  }
23489  case 7:
23490  {
23491  switch (currentRegion)
23492  {
23493  case 4: { result << coordsToPixels(keyMax, valueMax); break; }
23494  case 8: { result << coordsToPixels(keyMax, valueMax); break; }
23495  case 1: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMin, valueMax); break; }
23496  case 9: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMax, valueMin); break; }
23497  case 2: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; }
23498  case 6: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; }
23499  case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
23500  if ((value-prevValue)/(key-prevKey)*(keyMax-key)+value < valueMin) // segment passes below R
23501  { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); }
23502  else
23503  { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); }
23504  break;
23505  }
23506  }
23507  break;
23508  }
23509  case 8:
23510  {
23511  switch (currentRegion)
23512  {
23513  case 7: { result << coordsToPixels(keyMax, valueMax); break; }
23514  case 9: { result << coordsToPixels(keyMax, valueMin); break; }
23515  case 4: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; }
23516  case 6: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; }
23517  case 1: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); break; }
23518  case 3: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); break; }
23519  }
23520  break;
23521  }
23522  case 9:
23523  {
23524  switch (currentRegion)
23525  {
23526  case 6: { result << coordsToPixels(keyMax, valueMin); break; }
23527  case 8: { result << coordsToPixels(keyMax, valueMin); break; }
23528  case 3: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMin, valueMin); break; }
23529  case 7: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMax, valueMax); break; }
23530  case 2: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; }
23531  case 4: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; }
23532  case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points
23533  if ((value-prevValue)/(key-prevKey)*(keyMin-key)+value < valueMin) // segment passes below R
23534  { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); }
23535  else
23536  { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); }
23537  break;
23538  }
23539  }
23540  break;
23541  }
23542  }
23543  return result;
23544 }
23545 
23558 bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const
23559 {
23560  switch (prevRegion)
23561  {
23562  case 1:
23563  {
23564  switch (currentRegion)
23565  {
23566  case 4:
23567  case 7:
23568  case 2:
23569  case 3: return false;
23570  default: return true;
23571  }
23572  }
23573  case 2:
23574  {
23575  switch (currentRegion)
23576  {
23577  case 1:
23578  case 3: return false;
23579  default: return true;
23580  }
23581  }
23582  case 3:
23583  {
23584  switch (currentRegion)
23585  {
23586  case 1:
23587  case 2:
23588  case 6:
23589  case 9: return false;
23590  default: return true;
23591  }
23592  }
23593  case 4:
23594  {
23595  switch (currentRegion)
23596  {
23597  case 1:
23598  case 7: return false;
23599  default: return true;
23600  }
23601  }
23602  case 5: return false; // should never occur
23603  case 6:
23604  {
23605  switch (currentRegion)
23606  {
23607  case 3:
23608  case 9: return false;
23609  default: return true;
23610  }
23611  }
23612  case 7:
23613  {
23614  switch (currentRegion)
23615  {
23616  case 1:
23617  case 4:
23618  case 8:
23619  case 9: return false;
23620  default: return true;
23621  }
23622  }
23623  case 8:
23624  {
23625  switch (currentRegion)
23626  {
23627  case 7:
23628  case 9: return false;
23629  default: return true;
23630  }
23631  }
23632  case 9:
23633  {
23634  switch (currentRegion)
23635  {
23636  case 3:
23637  case 6:
23638  case 8:
23639  case 7: return false;
23640  default: return true;
23641  }
23642  }
23643  default: return true;
23644  }
23645 }
23646 
23647 
23661 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin, QPointF &crossA, QPointF &crossB) const
23662 {
23663  // The intersection point interpolation here is done in pixel coordinates, so we don't need to
23664  // differentiate between different axis scale types. Note that the nomenclature
23665  // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be
23666  // different in pixel coordinates (horz/vert key axes, reversed ranges)
23667 
23668  QList<QPointF> intersections;
23669  const double valueMinPx = mValueAxis->coordToPixel(valueMin);
23670  const double valueMaxPx = mValueAxis->coordToPixel(valueMax);
23671  const double keyMinPx = mKeyAxis->coordToPixel(keyMin);
23672  const double keyMaxPx = mKeyAxis->coordToPixel(keyMax);
23673  const double keyPx = mKeyAxis->coordToPixel(key);
23674  const double valuePx = mValueAxis->coordToPixel(value);
23675  const double prevKeyPx = mKeyAxis->coordToPixel(prevKey);
23676  const double prevValuePx = mValueAxis->coordToPixel(prevValue);
23677  if (qFuzzyIsNull(keyPx-prevKeyPx)) // line is parallel to value axis
23678  {
23679  // due to region filter in mayTraverse(), if line is parallel to value or key axis, region 5 is traversed here
23680  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyPx, valueMinPx) : QPointF(valueMinPx, keyPx)); // direction will be taken care of at end of method
23681  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyPx, valueMaxPx) : QPointF(valueMaxPx, keyPx));
23682  } else if (qFuzzyIsNull(valuePx-prevValuePx)) // line is parallel to key axis
23683  {
23684  // due to region filter in mayTraverse(), if line is parallel to value or key axis, region 5 is traversed here
23685  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMinPx, valuePx) : QPointF(valuePx, keyMinPx)); // direction will be taken care of at end of method
23686  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMaxPx, valuePx) : QPointF(valuePx, keyMaxPx));
23687  } else // line is skewed
23688  {
23689  double gamma;
23690  double keyPerValuePx = (keyPx-prevKeyPx)/(valuePx-prevValuePx);
23691  // check top of rect:
23692  gamma = prevKeyPx + (valueMaxPx-prevValuePx)*keyPerValuePx;
23693  if (gamma >= qMin(keyMinPx, keyMaxPx) && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed
23694  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(gamma, valueMaxPx) : QPointF(valueMaxPx, gamma));
23695  // check bottom of rect:
23696  gamma = prevKeyPx + (valueMinPx-prevValuePx)*keyPerValuePx;
23697  if (gamma >= qMin(keyMinPx, keyMaxPx) && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed
23698  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(gamma, valueMinPx) : QPointF(valueMinPx, gamma));
23699  const double valuePerKeyPx = 1.0/keyPerValuePx;
23700  // check left of rect:
23701  gamma = prevValuePx + (keyMinPx-prevKeyPx)*valuePerKeyPx;
23702  if (gamma >= qMin(valueMinPx, valueMaxPx) && gamma <= qMax(valueMinPx, valueMaxPx)) // qMin/qMax necessary since axes may be reversed
23703  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMinPx, gamma) : QPointF(gamma, keyMinPx));
23704  // check right of rect:
23705  gamma = prevValuePx + (keyMaxPx-prevKeyPx)*valuePerKeyPx;
23706  if (gamma >= qMin(valueMinPx, valueMaxPx) && gamma <= qMax(valueMinPx, valueMaxPx)) // qMin/qMax necessary since axes may be reversed
23707  intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMaxPx, gamma) : QPointF(gamma, keyMaxPx));
23708  }
23709 
23710  // handle cases where found points isn't exactly 2:
23711  if (intersections.size() > 2)
23712  {
23713  // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between:
23714  double distSqrMax = 0;
23715  QPointF pv1, pv2;
23716  for (int i=0; i<intersections.size()-1; ++i)
23717  {
23718  for (int k=i+1; k<intersections.size(); ++k)
23719  {
23720  QPointF distPoint = intersections.at(i)-intersections.at(k);
23721  double distSqr = distPoint.x()*distPoint.x()+distPoint.y()+distPoint.y();
23722  if (distSqr > distSqrMax)
23723  {
23724  pv1 = intersections.at(i);
23725  pv2 = intersections.at(k);
23726  distSqrMax = distSqr;
23727  }
23728  }
23729  }
23730  intersections = QList<QPointF>() << pv1 << pv2;
23731  } else if (intersections.size() != 2)
23732  {
23733  // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment
23734  return false;
23735  }
23736 
23737  // possibly re-sort points so optimized point segment has same direction as original segment:
23738  double xDelta = keyPx-prevKeyPx;
23739  double yDelta = valuePx-prevValuePx;
23740  if (mKeyAxis->orientation() != Qt::Horizontal)
23741  qSwap(xDelta, yDelta);
23742  if (xDelta*(intersections.at(1).x()-intersections.at(0).x()) + yDelta*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction
23743  intersections.move(0, 1);
23744  crossA = intersections.at(0);
23745  crossB = intersections.at(1);
23746  return true;
23747 }
23748 
23774 void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double keyMin, double valueMax, double keyMax, double valueMin, QVector<QPointF> &beforeTraverse, QVector<QPointF> &afterTraverse) const
23775 {
23776  switch (prevRegion)
23777  {
23778  case 1:
23779  {
23780  switch (currentRegion)
23781  {
23782  case 6: { beforeTraverse << coordsToPixels(keyMin, valueMax); break; }
23783  case 9: { beforeTraverse << coordsToPixels(keyMin, valueMax); afterTraverse << coordsToPixels(keyMax, valueMin); break; }
23784  case 8: { beforeTraverse << coordsToPixels(keyMin, valueMax); break; }
23785  }
23786  break;
23787  }
23788  case 2:
23789  {
23790  switch (currentRegion)
23791  {
23792  case 7: { afterTraverse << coordsToPixels(keyMax, valueMax); break; }
23793  case 9: { afterTraverse << coordsToPixels(keyMax, valueMin); break; }
23794  }
23795  break;
23796  }
23797  case 3:
23798  {
23799  switch (currentRegion)
23800  {
23801  case 4: { beforeTraverse << coordsToPixels(keyMin, valueMin); break; }
23802  case 7: { beforeTraverse << coordsToPixels(keyMin, valueMin); afterTraverse << coordsToPixels(keyMax, valueMax); break; }
23803  case 8: { beforeTraverse << coordsToPixels(keyMin, valueMin); break; }
23804  }
23805  break;
23806  }
23807  case 4:
23808  {
23809  switch (currentRegion)
23810  {
23811  case 3: { afterTraverse << coordsToPixels(keyMin, valueMin); break; }
23812  case 9: { afterTraverse << coordsToPixels(keyMax, valueMin); break; }
23813  }
23814  break;
23815  }
23816  case 5: { break; } // shouldn't happen because this method only handles full traverses
23817  case 6:
23818  {
23819  switch (currentRegion)
23820  {
23821  case 1: { afterTraverse << coordsToPixels(keyMin, valueMax); break; }
23822  case 7: { afterTraverse << coordsToPixels(keyMax, valueMax); break; }
23823  }
23824  break;
23825  }
23826  case 7:
23827  {
23828  switch (currentRegion)
23829  {
23830  case 2: { beforeTraverse << coordsToPixels(keyMax, valueMax); break; }
23831  case 3: { beforeTraverse << coordsToPixels(keyMax, valueMax); afterTraverse << coordsToPixels(keyMin, valueMin); break; }
23832  case 6: { beforeTraverse << coordsToPixels(keyMax, valueMax); break; }
23833  }
23834  break;
23835  }
23836  case 8:
23837  {
23838  switch (currentRegion)
23839  {
23840  case 1: { afterTraverse << coordsToPixels(keyMin, valueMax); break; }
23841  case 3: { afterTraverse << coordsToPixels(keyMin, valueMin); break; }
23842  }
23843  break;
23844  }
23845  case 9:
23846  {
23847  switch (currentRegion)
23848  {
23849  case 2: { beforeTraverse << coordsToPixels(keyMax, valueMin); break; }
23850  case 1: { beforeTraverse << coordsToPixels(keyMax, valueMin); afterTraverse << coordsToPixels(keyMin, valueMax); break; }
23851  case 4: { beforeTraverse << coordsToPixels(keyMax, valueMin); break; }
23852  }
23853  break;
23854  }
23855  }
23856 }
23857 
23870 double QCPCurve::pointDistance(const QPointF &pixelPoint, QCPCurveDataContainer::const_iterator &closestData) const
23871 {
23872  closestData = mDataContainer->constEnd();
23873  if (mDataContainer->isEmpty())
23874  return -1.0;
23875  if (mLineStyle == lsNone && mScatterStyle.isNone())
23876  return -1.0;
23877 
23878  if (mDataContainer->size() == 1)
23879  {
23880  QPointF dataPoint = coordsToPixels(mDataContainer->constBegin()->key, mDataContainer->constBegin()->value);
23881  closestData = mDataContainer->constBegin();
23882  return QCPVector2D(dataPoint-pixelPoint).length();
23883  }
23884 
23885  // calculate minimum distances to curve data points and find closestData iterator:
23886  double minDistSqr = (std::numeric_limits<double>::max)();
23887  // iterate over found data points and then choose the one with the shortest distance to pos:
23890  for (QCPCurveDataContainer::const_iterator it=begin; it!=end; ++it)
23891  {
23892  const double currentDistSqr = QCPVector2D(coordsToPixels(it->key, it->value)-pixelPoint).lengthSquared();
23893  if (currentDistSqr < minDistSqr)
23894  {
23895  minDistSqr = currentDistSqr;
23896  closestData = it;
23897  }
23898  }
23899 
23900  // calculate distance to line if there is one (if so, will probably be smaller than distance to closest data point):
23901  if (mLineStyle != lsNone)
23902  {
23903  QVector<QPointF> lines;
23904  getCurveLines(&lines, QCPDataRange(0, dataCount()), mParentPlot->selectionTolerance()*1.2); // optimized lines outside axis rect shouldn't respond to clicks at the edge, so use 1.2*tolerance as pen width
23905  for (int i=0; i<lines.size()-1; ++i)
23906  {
23907  double currentDistSqr = QCPVector2D(pixelPoint).distanceSquaredToLine(lines.at(i), lines.at(i+1));
23908  if (currentDistSqr < minDistSqr)
23909  minDistSqr = currentDistSqr;
23910  }
23911  }
23912 
23913  return qSqrt(minDistSqr);
23914 }
23915 /* end of 'src/plottables/plottable-curve.cpp' */
23916 
23917 
23918 /* including file 'src/plottables/plottable-bars.cpp' */
23919 /* modified 2021-03-29T02:30:44, size 43907 */
23920 
23921 
23925 
23960 /* start of documentation of inline functions */
23961 
23988 /* end of documentation of inline functions */
23989 
23994  QObject(parentPlot),
23995  mParentPlot(parentPlot),
23996  mSpacingType(stAbsolute),
23997  mSpacing(4)
23998 {
23999 }
24000 
24002 {
24003  clear();
24004 }
24005 
24014 {
24016 }
24017 
24024 void QCPBarsGroup::setSpacing(double spacing)
24025 {
24026  mSpacing = spacing;
24027 }
24028 
24035 QCPBars *QCPBarsGroup::bars(int index) const
24036 {
24037  if (index >= 0 && index < mBars.size())
24038  {
24039  return mBars.at(index);
24040  } else
24041  {
24042  qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
24043  return nullptr;
24044  }
24045 }
24046 
24053 {
24054  const QList<QCPBars*> oldBars = mBars;
24055  foreach (QCPBars *bars, oldBars)
24056  bars->setBarsGroup(nullptr); // removes itself from mBars via removeBars
24057 }
24058 
24066 {
24067  if (!bars)
24068  {
24069  qDebug() << Q_FUNC_INFO << "bars is 0";
24070  return;
24071  }
24072 
24073  if (!mBars.contains(bars))
24074  bars->setBarsGroup(this);
24075  else
24076  qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast<quintptr>(bars);
24077 }
24078 
24088 void QCPBarsGroup::insert(int i, QCPBars *bars)
24089 {
24090  if (!bars)
24091  {
24092  qDebug() << Q_FUNC_INFO << "bars is 0";
24093  return;
24094  }
24095 
24096  // first append to bars list normally:
24097  if (!mBars.contains(bars))
24098  bars->setBarsGroup(this);
24099  // then move to according position:
24100  mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1));
24101 }
24102 
24109 {
24110  if (!bars)
24111  {
24112  qDebug() << Q_FUNC_INFO << "bars is 0";
24113  return;
24114  }
24115 
24116  if (mBars.contains(bars))
24117  bars->setBarsGroup(nullptr);
24118  else
24119  qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast<quintptr>(bars);
24120 }
24121 
24130 {
24131  if (!mBars.contains(bars))
24132  mBars.append(bars);
24133 }
24134 
24143 {
24144  mBars.removeOne(bars);
24145 }
24146 
24153 double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord)
24154 {
24155  // find list of all base bars in case some mBars are stacked:
24156  QList<const QCPBars*> baseBars;
24157  foreach (const QCPBars *b, mBars)
24158  {
24159  while (b->barBelow())
24160  b = b->barBelow();
24161  if (!baseBars.contains(b))
24162  baseBars.append(b);
24163  }
24164  // find base bar this "bars" is stacked on:
24165  const QCPBars *thisBase = bars;
24166  while (thisBase->barBelow())
24167  thisBase = thisBase->barBelow();
24168 
24169  // determine key pixel offset of this base bars considering all other base bars in this barsgroup:
24170  double result = 0;
24171  int index = baseBars.indexOf(thisBase);
24172  if (index >= 0)
24173  {
24174  if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose)
24175  {
24176  return result;
24177  } else
24178  {
24179  double lowerPixelWidth, upperPixelWidth;
24180  int startIndex;
24181  int dir = (index <= (baseBars.size()-1)/2) ? -1 : 1; // if bar is to lower keys of center, dir is negative
24182  if (baseBars.size() % 2 == 0) // even number of bars
24183  {
24184  startIndex = baseBars.size()/2 + (dir < 0 ? -1 : 0);
24185  result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing
24186  } else // uneven number of bars
24187  {
24188  startIndex = (baseBars.size()-1)/2+dir;
24189  baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
24190  result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar
24191  result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing
24192  }
24193  for (int i = startIndex; i != index; i += dir) // add widths and spacings of bars in between center and our bars
24194  {
24195  baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
24196  result += qAbs(upperPixelWidth-lowerPixelWidth);
24197  result += getPixelSpacing(baseBars.at(i), keyCoord);
24198  }
24199  // finally half of our bars width:
24200  baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
24201  result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
24202  // correct sign of result depending on orientation and direction of key axis:
24203  result *= dir*thisBase->keyAxis()->pixelOrientation();
24204  }
24205  }
24206  return result;
24207 }
24208 
24219 double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord)
24220 {
24221  switch (mSpacingType)
24222  {
24223  case stAbsolute:
24224  {
24225  return mSpacing;
24226  }
24227  case stAxisRectRatio:
24228  {
24229  if (bars->keyAxis()->orientation() == Qt::Horizontal)
24230  return bars->keyAxis()->axisRect()->width()*mSpacing;
24231  else
24232  return bars->keyAxis()->axisRect()->height()*mSpacing;
24233  }
24234  case stPlotCoords:
24235  {
24236  double keyPixel = bars->keyAxis()->coordToPixel(keyCoord);
24237  return qAbs(bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel);
24238  }
24239  }
24240  return 0;
24241 }
24242 
24243 
24247 
24262 /* start documentation of inline functions */
24263 
24313 /* end documentation of inline functions */
24314 
24319  key(0),
24320  value(0)
24321 {
24322 }
24323 
24327 QCPBarsData::QCPBarsData(double key, double value) :
24328  key(key),
24329  value(value)
24330 {
24331 }
24332 
24333 
24337 
24373 /* start of documentation of inline functions */
24374 
24396 /* end of documentation of inline functions */
24397 
24408 QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) :
24409  QCPAbstractPlottable1D<QCPBarsData>(keyAxis, valueAxis),
24410  mWidth(0.75),
24411  mWidthType(wtPlotCoords),
24412  mBarsGroup(nullptr),
24413  mBaseValue(0),
24414  mStackingGap(1)
24415 {
24416  // modify inherited properties from abstract plottable:
24417  mPen.setColor(Qt::blue);
24418  mPen.setStyle(Qt::SolidLine);
24419  mBrush.setColor(QColor(40, 50, 255, 30));
24420  mBrush.setStyle(Qt::SolidPattern);
24421  mSelectionDecorator->setBrush(QBrush(QColor(160, 160, 255)));
24422 }
24423 
24425 {
24426  setBarsGroup(nullptr);
24427  if (mBarBelow || mBarAbove)
24428  connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking
24429 }
24430 
24446 void QCPBars::setData(QSharedPointer<QCPBarsDataContainer> data)
24447 {
24448  mDataContainer = data;
24449 }
24450 
24462 void QCPBars::setData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
24463 {
24464  mDataContainer->clear();
24465  addData(keys, values, alreadySorted);
24466 }
24467 
24474 void QCPBars::setWidth(double width)
24475 {
24476  mWidth = width;
24477 }
24478 
24488 {
24490 }
24491 
24499 {
24500  // deregister at old group:
24501  if (mBarsGroup)
24502  mBarsGroup->unregisterBars(this);
24504  // register at new group:
24505  if (mBarsGroup)
24506  mBarsGroup->registerBars(this);
24507 }
24508 
24521 void QCPBars::setBaseValue(double baseValue)
24522 {
24524 }
24525 
24531 void QCPBars::setStackingGap(double pixels)
24532 {
24533  mStackingGap = pixels;
24534 }
24535 
24548 void QCPBars::addData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
24549 {
24550  if (keys.size() != values.size())
24551  qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size();
24552  const int n = qMin(keys.size(), values.size());
24553  QVector<QCPBarsData> tempData(n);
24554  QVector<QCPBarsData>::iterator it = tempData.begin();
24555  const QVector<QCPBarsData>::iterator itEnd = tempData.end();
24556  int i = 0;
24557  while (it != itEnd)
24558  {
24559  it->key = keys[i];
24560  it->value = values[i];
24561  ++it;
24562  ++i;
24563  }
24564  mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write
24565 }
24566 
24573 void QCPBars::addData(double key, double value)
24574 {
24575  mDataContainer->add(QCPBarsData(key, value));
24576 }
24577 
24593 {
24594  if (bars == this) return;
24595  if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
24596  {
24597  qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
24598  return;
24599  }
24600  // remove from stacking:
24601  connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
24602  // if new bar given, insert this bar below it:
24603  if (bars)
24604  {
24605  if (bars->mBarBelow)
24606  connectBars(bars->mBarBelow.data(), this);
24607  connectBars(this, bars);
24608  }
24609 }
24610 
24626 {
24627  if (bars == this) return;
24628  if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data()))
24629  {
24630  qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars";
24631  return;
24632  }
24633  // remove from stacking:
24634  connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0
24635  // if new bar given, insert this bar above it:
24636  if (bars)
24637  {
24638  if (bars->mBarAbove)
24639  connectBars(this, bars->mBarAbove.data());
24640  connectBars(bars, this);
24641  }
24642 }
24643 
24647 QCPDataSelection QCPBars::selectTestRect(const QRectF &rect, bool onlySelectable) const
24648 {
24649  QCPDataSelection result;
24650  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
24651  return result;
24652  if (!mKeyAxis || !mValueAxis)
24653  return result;
24654 
24655  QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd;
24656  getVisibleDataBounds(visibleBegin, visibleEnd);
24657 
24658  for (QCPBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
24659  {
24660  if (rect.intersects(getBarRect(it->key, it->value)))
24661  result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false);
24662  }
24663  result.simplify();
24664  return result;
24665 }
24666 
24675 double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
24676 {
24677  Q_UNUSED(details)
24678  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
24679  return -1;
24680  if (!mKeyAxis || !mValueAxis)
24681  return -1;
24682 
24683  if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
24684  {
24685  // get visible data range:
24686  QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd;
24687  getVisibleDataBounds(visibleBegin, visibleEnd);
24688  for (QCPBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
24689  {
24690  if (getBarRect(it->key, it->value).contains(pos))
24691  {
24692  if (details)
24693  {
24694  int pointIndex = int(it-mDataContainer->constBegin());
24695  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
24696  }
24697  return mParentPlot->selectionTolerance()*0.99;
24698  }
24699  }
24700  }
24701  return -1;
24702 }
24703 
24704 /* inherits documentation from base class */
24705 QCPRange QCPBars::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
24706 {
24707  /* Note: If this QCPBars uses absolute pixels as width (or is in a QCPBarsGroup with spacing in
24708  absolute pixels), using this method to adapt the key axis range to fit the bars into the
24709  currently visible axis range will not work perfectly. Because in the moment the axis range is
24710  changed to the new range, the fixed pixel widths/spacings will represent different coordinate
24711  spans than before, which in turn would require a different key range to perfectly fit, and so on.
24712  The only solution would be to iteratively approach the perfect fitting axis range, but the
24713  mismatch isn't large enough in most applications, to warrant this here. If a user does need a
24714  better fit, he should call the corresponding axis rescale multiple times in a row.
24715  */
24716  QCPRange range;
24717  range = mDataContainer->keyRange(foundRange, inSignDomain);
24718 
24719  // determine exact range of bars by including bar width and barsgroup offset:
24720  if (foundRange && mKeyAxis)
24721  {
24722  double lowerPixelWidth, upperPixelWidth, keyPixel;
24723  // lower range bound:
24724  getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth);
24725  keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth;
24726  if (mBarsGroup)
24727  keyPixel += mBarsGroup->keyPixelOffset(this, range.lower);
24728  const double lowerCorrected = mKeyAxis.data()->pixelToCoord(keyPixel);
24729  if (!qIsNaN(lowerCorrected) && qIsFinite(lowerCorrected) && range.lower > lowerCorrected)
24730  range.lower = lowerCorrected;
24731  // upper range bound:
24732  getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth);
24733  keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth;
24734  if (mBarsGroup)
24735  keyPixel += mBarsGroup->keyPixelOffset(this, range.upper);
24736  const double upperCorrected = mKeyAxis.data()->pixelToCoord(keyPixel);
24737  if (!qIsNaN(upperCorrected) && qIsFinite(upperCorrected) && range.upper < upperCorrected)
24738  range.upper = upperCorrected;
24739  }
24740  return range;
24741 }
24742 
24743 /* inherits documentation from base class */
24744 QCPRange QCPBars::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
24745 {
24746  // Note: can't simply use mDataContainer->valueRange here because we need to
24747  // take into account bar base value and possible stacking of multiple bars
24748  QCPRange range;
24749  range.lower = mBaseValue;
24750  range.upper = mBaseValue;
24751  bool haveLower = true; // set to true, because baseValue should always be visible in bar charts
24752  bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts
24753  QCPBarsDataContainer::const_iterator itBegin = mDataContainer->constBegin();
24755  if (inKeyRange != QCPRange())
24756  {
24757  itBegin = mDataContainer->findBegin(inKeyRange.lower, false);
24758  itEnd = mDataContainer->findEnd(inKeyRange.upper, false);
24759  }
24760  for (QCPBarsDataContainer::const_iterator it = itBegin; it != itEnd; ++it)
24761  {
24762  const double current = it->value + getStackedBaseValue(it->key, it->value >= 0);
24763  if (qIsNaN(current)) continue;
24764  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
24765  {
24766  if (current < range.lower || !haveLower)
24767  {
24768  range.lower = current;
24769  haveLower = true;
24770  }
24771  if (current > range.upper || !haveUpper)
24772  {
24773  range.upper = current;
24774  haveUpper = true;
24775  }
24776  }
24777  }
24778 
24779  foundRange = true; // return true because bar charts always have the 0-line visible
24780  return range;
24781 }
24782 
24783 /* inherits documentation from base class */
24784 QPointF QCPBars::dataPixelPosition(int index) const
24785 {
24786  if (index >= 0 && index < mDataContainer->size())
24787  {
24788  QCPAxis *keyAxis = mKeyAxis.data();
24789  QCPAxis *valueAxis = mValueAxis.data();
24790  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; }
24791 
24792  const QCPDataContainer<QCPBarsData>::const_iterator it = mDataContainer->constBegin()+index;
24793  const double valuePixel = valueAxis->coordToPixel(getStackedBaseValue(it->key, it->value >= 0) + it->value);
24794  const double keyPixel = keyAxis->coordToPixel(it->key) + (mBarsGroup ? mBarsGroup->keyPixelOffset(this, it->key) : 0);
24795  if (keyAxis->orientation() == Qt::Horizontal)
24796  return {keyPixel, valuePixel};
24797  else
24798  return {valuePixel, keyPixel};
24799  } else
24800  {
24801  qDebug() << Q_FUNC_INFO << "Index out of bounds" << index;
24802  return {};
24803  }
24804 }
24805 
24806 /* inherits documentation from base class */
24808 {
24809  if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
24810  if (mDataContainer->isEmpty()) return;
24811 
24812  QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd;
24813  getVisibleDataBounds(visibleBegin, visibleEnd);
24814 
24815  // loop over and draw segments of unselected/selected data:
24816  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
24817  getDataSegments(selectedSegments, unselectedSegments);
24818  allSegments << unselectedSegments << selectedSegments;
24819  for (int i=0; i<allSegments.size(); ++i)
24820  {
24821  bool isSelectedSegment = i >= unselectedSegments.size();
24822  QCPBarsDataContainer::const_iterator begin = visibleBegin;
24823  QCPBarsDataContainer::const_iterator end = visibleEnd;
24824  mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
24825  if (begin == end)
24826  continue;
24827 
24828  for (QCPBarsDataContainer::const_iterator it=begin; it!=end; ++it)
24829  {
24830  // check data validity if flag set:
24831 #ifdef QCUSTOMPLOT_CHECK_DATA
24832  if (QCP::isInvalidData(it->key, it->value))
24833  qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "of drawn range invalid." << "Plottable name:" << name();
24834 #endif
24835  // draw bar:
24836  if (isSelectedSegment && mSelectionDecorator)
24837  {
24838  mSelectionDecorator->applyBrush(painter);
24839  mSelectionDecorator->applyPen(painter);
24840  } else
24841  {
24842  painter->setBrush(mBrush);
24843  painter->setPen(mPen);
24844  }
24846  painter->drawPolygon(getBarRect(it->key, it->value));
24847  }
24848  }
24849 
24850  // draw other selection decoration that isn't just line/scatter pens and brushes:
24851  if (mSelectionDecorator)
24853 }
24854 
24855 /* inherits documentation from base class */
24856 void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
24857 {
24858  // draw filled rect:
24860  painter->setBrush(mBrush);
24861  painter->setPen(mPen);
24862  QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
24863  r.moveCenter(rect.center());
24864  painter->drawRect(r);
24865 }
24866 
24882 {
24883  if (!mKeyAxis)
24884  {
24885  qDebug() << Q_FUNC_INFO << "invalid key axis";
24886  begin = mDataContainer->constEnd();
24887  end = mDataContainer->constEnd();
24888  return;
24889  }
24890  if (mDataContainer->isEmpty())
24891  {
24892  begin = mDataContainer->constEnd();
24893  end = mDataContainer->constEnd();
24894  return;
24895  }
24896 
24897  // get visible data range as QMap iterators
24898  begin = mDataContainer->findBegin(mKeyAxis.data()->range().lower);
24899  end = mDataContainer->findEnd(mKeyAxis.data()->range().upper);
24900  double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower);
24901  double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper);
24902  bool isVisible = false;
24903  // walk left from begin to find lower bar that actually is completely outside visible pixel range:
24905  while (it != mDataContainer->constBegin())
24906  {
24907  --it;
24908  const QRectF barRect = getBarRect(it->key, it->value);
24909  if (mKeyAxis.data()->orientation() == Qt::Horizontal)
24910  isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.left() <= lowerPixelBound));
24911  else // keyaxis is vertical
24912  isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.bottom() >= lowerPixelBound));
24913  if (isVisible)
24914  begin = it;
24915  else
24916  break;
24917  }
24918  // walk right from ubound to find upper bar that actually is completely outside visible pixel range:
24919  it = end;
24920  while (it != mDataContainer->constEnd())
24921  {
24922  const QRectF barRect = getBarRect(it->key, it->value);
24923  if (mKeyAxis.data()->orientation() == Qt::Horizontal)
24924  isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.right() >= upperPixelBound));
24925  else // keyaxis is vertical
24926  isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.top() <= upperPixelBound));
24927  if (isVisible)
24928  end = it+1;
24929  else
24930  break;
24931  ++it;
24932  }
24933 }
24934 
24941 QRectF QCPBars::getBarRect(double key, double value) const
24942 {
24943  QCPAxis *keyAxis = mKeyAxis.data();
24944  QCPAxis *valueAxis = mValueAxis.data();
24945  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; }
24946 
24947  double lowerPixelWidth, upperPixelWidth;
24948  getPixelWidth(key, lowerPixelWidth, upperPixelWidth);
24949  double base = getStackedBaseValue(key, value >= 0);
24950  double basePixel = valueAxis->coordToPixel(base);
24951  double valuePixel = valueAxis->coordToPixel(base+value);
24952  double keyPixel = keyAxis->coordToPixel(key);
24953  if (mBarsGroup)
24954  keyPixel += mBarsGroup->keyPixelOffset(this, key);
24955  double bottomOffset = (mBarBelow && mPen != Qt::NoPen ? 1 : 0)*(mPen.isCosmetic() ? 1 : mPen.widthF());
24956  bottomOffset += mBarBelow ? mStackingGap : 0;
24957  bottomOffset *= (value<0 ? -1 : 1)*valueAxis->pixelOrientation();
24958  if (qAbs(valuePixel-basePixel) <= qAbs(bottomOffset))
24959  bottomOffset = valuePixel-basePixel;
24960  if (keyAxis->orientation() == Qt::Horizontal)
24961  {
24962  return QRectF(QPointF(keyPixel+lowerPixelWidth, valuePixel), QPointF(keyPixel+upperPixelWidth, basePixel+bottomOffset)).normalized();
24963  } else
24964  {
24965  return QRectF(QPointF(basePixel+bottomOffset, keyPixel+lowerPixelWidth), QPointF(valuePixel, keyPixel+upperPixelWidth)).normalized();
24966  }
24967 }
24968 
24978 void QCPBars::getPixelWidth(double key, double &lower, double &upper) const
24979 {
24980  lower = 0;
24981  upper = 0;
24982  switch (mWidthType)
24983  {
24984  case wtAbsolute:
24985  {
24986  upper = mWidth*0.5*mKeyAxis.data()->pixelOrientation();
24987  lower = -upper;
24988  break;
24989  }
24990  case wtAxisRectRatio:
24991  {
24992  if (mKeyAxis && mKeyAxis.data()->axisRect())
24993  {
24994  if (mKeyAxis.data()->orientation() == Qt::Horizontal)
24995  upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5*mKeyAxis.data()->pixelOrientation();
24996  else
24997  upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5*mKeyAxis.data()->pixelOrientation();
24998  lower = -upper;
24999  } else
25000  qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined";
25001  break;
25002  }
25003  case wtPlotCoords:
25004  {
25005  if (mKeyAxis)
25006  {
25007  double keyPixel = mKeyAxis.data()->coordToPixel(key);
25008  upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel;
25009  lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel;
25010  // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by
25011  // coordinate transform which includes range direction
25012  } else
25013  qDebug() << Q_FUNC_INFO << "No key axis defined";
25014  break;
25015  }
25016  }
25017 }
25018 
25028 double QCPBars::getStackedBaseValue(double key, bool positive) const
25029 {
25030  if (mBarBelow)
25031  {
25032  double max = 0; // don't initialize with mBaseValue here because only base value of bottom-most bar has meaning in a bar stack
25033  // find bars of mBarBelow that are approximately at key and find largest one:
25034  double epsilon = qAbs(key)*(sizeof(key)==4 ? 1e-6 : 1e-14); // should be safe even when changed to use float at some point
25035  if (key == 0)
25036  epsilon = (sizeof(key)==4 ? 1e-6 : 1e-14);
25037  QCPBarsDataContainer::const_iterator it = mBarBelow.data()->mDataContainer->findBegin(key-epsilon);
25038  QCPBarsDataContainer::const_iterator itEnd = mBarBelow.data()->mDataContainer->findEnd(key+epsilon);
25039  while (it != itEnd)
25040  {
25041  if (it->key > key-epsilon && it->key < key+epsilon)
25042  {
25043  if ((positive && it->value > max) ||
25044  (!positive && it->value < max))
25045  max = it->value;
25046  }
25047  ++it;
25048  }
25049  // recurse down the bar-stack to find the total height:
25050  return max + mBarBelow.data()->getStackedBaseValue(key, positive);
25051  } else
25052  return mBaseValue;
25053 }
25054 
25064 {
25065  if (!lower && !upper) return;
25066 
25067  if (!lower) // disconnect upper at bottom
25068  {
25069  // disconnect old bar below upper:
25070  if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
25071  upper->mBarBelow.data()->mBarAbove = nullptr;
25072  upper->mBarBelow = nullptr;
25073  } else if (!upper) // disconnect lower at top
25074  {
25075  // disconnect old bar above lower:
25076  if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
25077  lower->mBarAbove.data()->mBarBelow = nullptr;
25078  lower->mBarAbove = nullptr;
25079  } else // connect lower and upper
25080  {
25081  // disconnect old bar above lower:
25082  if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower)
25083  lower->mBarAbove.data()->mBarBelow = nullptr;
25084  // disconnect old bar below upper:
25085  if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper)
25086  upper->mBarBelow.data()->mBarAbove = nullptr;
25087  lower->mBarAbove = upper;
25088  upper->mBarBelow = lower;
25089  }
25090 }
25091 /* end of 'src/plottables/plottable-bars.cpp' */
25092 
25093 
25094 /* including file 'src/plottables/plottable-statisticalbox.cpp' */
25095 /* modified 2021-03-29T02:30:44, size 28951 */
25096 
25100 
25136 /* start documentation of inline functions */
25137 
25188 /* end documentation of inline functions */
25189 
25194  key(0),
25195  minimum(0),
25196  lowerQuartile(0),
25197  median(0),
25198  upperQuartile(0),
25199  maximum(0)
25200 {
25201 }
25202 
25207 QCPStatisticalBoxData::QCPStatisticalBoxData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector<double> &outliers) :
25208  key(key),
25209  minimum(minimum),
25210  lowerQuartile(lowerQuartile),
25211  median(median),
25212  upperQuartile(upperQuartile),
25213  maximum(maximum),
25214  outliers(outliers)
25215 {
25216 }
25217 
25218 
25222 
25271 /* start documentation of inline functions */
25272 
25280 /* end documentation of inline functions */
25281 
25293  QCPAbstractPlottable1D<QCPStatisticalBoxData>(keyAxis, valueAxis),
25294  mWidth(0.5),
25295  mWhiskerWidth(0.2),
25296  mWhiskerPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap),
25297  mWhiskerBarPen(Qt::black),
25298  mWhiskerAntialiased(false),
25299  mMedianPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap),
25300  mOutlierStyle(QCPScatterStyle::ssCircle, Qt::blue, 6)
25301 {
25302  setPen(QPen(Qt::black));
25303  setBrush(Qt::NoBrush);
25304 }
25305 
25322 void QCPStatisticalBox::setData(QSharedPointer<QCPStatisticalBoxDataContainer> data)
25323 {
25324  mDataContainer = data;
25325 }
25337 void QCPStatisticalBox::setData(const QVector<double> &keys, const QVector<double> &minimum, const QVector<double> &lowerQuartile, const QVector<double> &median, const QVector<double> &upperQuartile, const QVector<double> &maximum, bool alreadySorted)
25338 {
25339  mDataContainer->clear();
25340  addData(keys, minimum, lowerQuartile, median, upperQuartile, maximum, alreadySorted);
25341 }
25342 
25349 {
25350  mWidth = width;
25351 }
25352 
25362 {
25363  mWhiskerWidth = width;
25364 }
25365 
25378 {
25379  mWhiskerPen = pen;
25380 }
25381 
25392 {
25393  mWhiskerBarPen = pen;
25394 }
25395 
25403 {
25404  mWhiskerAntialiased = enabled;
25405 }
25406 
25410 void QCPStatisticalBox::setMedianPen(const QPen &pen)
25411 {
25412  mMedianPen = pen;
25413 }
25414 
25422 {
25423  mOutlierStyle = style;
25424 }
25425 
25438 void QCPStatisticalBox::addData(const QVector<double> &keys, const QVector<double> &minimum, const QVector<double> &lowerQuartile, const QVector<double> &median, const QVector<double> &upperQuartile, const QVector<double> &maximum, bool alreadySorted)
25439 {
25440  if (keys.size() != minimum.size() || minimum.size() != lowerQuartile.size() || lowerQuartile.size() != median.size() ||
25441  median.size() != upperQuartile.size() || upperQuartile.size() != maximum.size() || maximum.size() != keys.size())
25442  qDebug() << Q_FUNC_INFO << "keys, minimum, lowerQuartile, median, upperQuartile, maximum have different sizes:"
25443  << keys.size() << minimum.size() << lowerQuartile.size() << median.size() << upperQuartile.size() << maximum.size();
25444  const int n = qMin(keys.size(), qMin(minimum.size(), qMin(lowerQuartile.size(), qMin(median.size(), qMin(upperQuartile.size(), maximum.size())))));
25445  QVector<QCPStatisticalBoxData> tempData(n);
25446  QVector<QCPStatisticalBoxData>::iterator it = tempData.begin();
25447  const QVector<QCPStatisticalBoxData>::iterator itEnd = tempData.end();
25448  int i = 0;
25449  while (it != itEnd)
25450  {
25451  it->key = keys[i];
25452  it->minimum = minimum[i];
25453  it->lowerQuartile = lowerQuartile[i];
25454  it->median = median[i];
25455  it->upperQuartile = upperQuartile[i];
25456  it->maximum = maximum[i];
25457  ++it;
25458  ++i;
25459  }
25460  mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write
25461 }
25462 
25471 void QCPStatisticalBox::addData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector<double> &outliers)
25472 {
25473  mDataContainer->add(QCPStatisticalBoxData(key, minimum, lowerQuartile, median, upperQuartile, maximum, outliers));
25474 }
25475 
25479 QCPDataSelection QCPStatisticalBox::selectTestRect(const QRectF &rect, bool onlySelectable) const
25480 {
25481  QCPDataSelection result;
25482  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
25483  return result;
25484  if (!mKeyAxis || !mValueAxis)
25485  return result;
25486 
25487  QCPStatisticalBoxDataContainer::const_iterator visibleBegin, visibleEnd;
25488  getVisibleDataBounds(visibleBegin, visibleEnd);
25489 
25490  for (QCPStatisticalBoxDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
25491  {
25492  if (rect.intersects(getQuartileBox(it)))
25493  result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false);
25494  }
25495  result.simplify();
25496  return result;
25497 }
25498 
25507 double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
25508 {
25509  Q_UNUSED(details)
25510  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
25511  return -1;
25512  if (!mKeyAxis || !mValueAxis)
25513  return -1;
25514 
25515  if (mKeyAxis->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
25516  {
25517  // get visible data range:
25518  QCPStatisticalBoxDataContainer::const_iterator visibleBegin, visibleEnd;
25519  QCPStatisticalBoxDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd();
25520  getVisibleDataBounds(visibleBegin, visibleEnd);
25521  double minDistSqr = (std::numeric_limits<double>::max)();
25522  for (QCPStatisticalBoxDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
25523  {
25524  if (getQuartileBox(it).contains(pos)) // quartile box
25525  {
25526  double currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
25527  if (currentDistSqr < minDistSqr)
25528  {
25529  minDistSqr = currentDistSqr;
25530  closestDataPoint = it;
25531  }
25532  } else // whiskers
25533  {
25534  const QVector<QLineF> whiskerBackbones = getWhiskerBackboneLines(it);
25535  const QCPVector2D posVec(pos);
25536  foreach (const QLineF &backbone, whiskerBackbones)
25537  {
25538  double currentDistSqr = posVec.distanceSquaredToLine(backbone);
25539  if (currentDistSqr < minDistSqr)
25540  {
25541  minDistSqr = currentDistSqr;
25542  closestDataPoint = it;
25543  }
25544  }
25545  }
25546  }
25547  if (details)
25548  {
25549  int pointIndex = int(closestDataPoint-mDataContainer->constBegin());
25550  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
25551  }
25552  return qSqrt(minDistSqr);
25553  }
25554  return -1;
25555 }
25556 
25557 /* inherits documentation from base class */
25558 QCPRange QCPStatisticalBox::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
25559 {
25560  QCPRange range = mDataContainer->keyRange(foundRange, inSignDomain);
25561  // determine exact range by including width of bars/flags:
25562  if (foundRange)
25563  {
25564  if (inSignDomain != QCP::sdPositive || range.lower-mWidth*0.5 > 0)
25565  range.lower -= mWidth*0.5;
25566  if (inSignDomain != QCP::sdNegative || range.upper+mWidth*0.5 < 0)
25567  range.upper += mWidth*0.5;
25568  }
25569  return range;
25570 }
25571 
25572 /* inherits documentation from base class */
25573 QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
25574 {
25575  return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
25576 }
25577 
25578 /* inherits documentation from base class */
25580 {
25581  if (mDataContainer->isEmpty()) return;
25582  QCPAxis *keyAxis = mKeyAxis.data();
25583  QCPAxis *valueAxis = mValueAxis.data();
25584  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
25585 
25586  QCPStatisticalBoxDataContainer::const_iterator visibleBegin, visibleEnd;
25587  getVisibleDataBounds(visibleBegin, visibleEnd);
25588 
25589  // loop over and draw segments of unselected/selected data:
25590  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
25591  getDataSegments(selectedSegments, unselectedSegments);
25592  allSegments << unselectedSegments << selectedSegments;
25593  for (int i=0; i<allSegments.size(); ++i)
25594  {
25595  bool isSelectedSegment = i >= unselectedSegments.size();
25598  mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
25599  if (begin == end)
25600  continue;
25601 
25602  for (QCPStatisticalBoxDataContainer::const_iterator it=begin; it!=end; ++it)
25603  {
25604  // check data validity if flag set:
25605 # ifdef QCUSTOMPLOT_CHECK_DATA
25606  if (QCP::isInvalidData(it->key, it->minimum) ||
25607  QCP::isInvalidData(it->lowerQuartile, it->median) ||
25608  QCP::isInvalidData(it->upperQuartile, it->maximum))
25609  qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "of drawn range has invalid data." << "Plottable name:" << name();
25610  for (int i=0; i<it->outliers.size(); ++i)
25611  if (QCP::isInvalidData(it->outliers.at(i)))
25612  qDebug() << Q_FUNC_INFO << "Data point outlier at" << it->key << "of drawn range invalid." << "Plottable name:" << name();
25613 # endif
25614 
25615  if (isSelectedSegment && mSelectionDecorator)
25616  {
25617  mSelectionDecorator->applyPen(painter);
25618  mSelectionDecorator->applyBrush(painter);
25619  } else
25620  {
25621  painter->setPen(mPen);
25622  painter->setBrush(mBrush);
25623  }
25624  QCPScatterStyle finalOutlierStyle = mOutlierStyle;
25625  if (isSelectedSegment && mSelectionDecorator)
25627  drawStatisticalBox(painter, it, finalOutlierStyle);
25628  }
25629  }
25630 
25631  // draw other selection decoration that isn't just line/scatter pens and brushes:
25632  if (mSelectionDecorator)
25634 }
25635 
25636 /* inherits documentation from base class */
25637 void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
25638 {
25639  // draw filled rect:
25641  painter->setPen(mPen);
25642  painter->setBrush(mBrush);
25643  QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
25644  r.moveCenter(rect.center());
25645  painter->drawRect(r);
25646 }
25647 
25657 {
25658  // draw quartile box:
25660  const QRectF quartileBox = getQuartileBox(it);
25661  painter->drawRect(quartileBox);
25662  // draw median line with cliprect set to quartile box:
25663  painter->save();
25664  painter->setClipRect(quartileBox, Qt::IntersectClip);
25665  painter->setPen(mMedianPen);
25666  painter->drawLine(QLineF(coordsToPixels(it->key-mWidth*0.5, it->median), coordsToPixels(it->key+mWidth*0.5, it->median)));
25667  painter->restore();
25668  // draw whisker lines:
25670  painter->setPen(mWhiskerPen);
25671  painter->drawLines(getWhiskerBackboneLines(it));
25672  painter->setPen(mWhiskerBarPen);
25673  painter->drawLines(getWhiskerBarLines(it));
25674  // draw outliers:
25676  outlierStyle.applyTo(painter, mPen);
25677  for (int i=0; i<it->outliers.size(); ++i)
25678  outlierStyle.drawShape(painter, coordsToPixels(it->key, it->outliers.at(i)));
25679 }
25680 
25696 {
25697  if (!mKeyAxis)
25698  {
25699  qDebug() << Q_FUNC_INFO << "invalid key axis";
25700  begin = mDataContainer->constEnd();
25701  end = mDataContainer->constEnd();
25702  return;
25703  }
25704  begin = mDataContainer->findBegin(mKeyAxis.data()->range().lower-mWidth*0.5); // subtract half width of box to include partially visible data points
25705  end = mDataContainer->findEnd(mKeyAxis.data()->range().upper+mWidth*0.5); // add half width of box to include partially visible data points
25706 }
25707 
25716 {
25717  QRectF result;
25718  result.setTopLeft(coordsToPixels(it->key-mWidth*0.5, it->upperQuartile));
25719  result.setBottomRight(coordsToPixels(it->key+mWidth*0.5, it->lowerQuartile));
25720  return result;
25721 }
25722 
25732 {
25733  QVector<QLineF> result(2);
25734  result[0].setPoints(coordsToPixels(it->key, it->lowerQuartile), coordsToPixels(it->key, it->minimum)); // min backbone
25735  result[1].setPoints(coordsToPixels(it->key, it->upperQuartile), coordsToPixels(it->key, it->maximum)); // max backbone
25736  return result;
25737 }
25738 
25747 {
25748  QVector<QLineF> result(2);
25749  result[0].setPoints(coordsToPixels(it->key-mWhiskerWidth*0.5, it->minimum), coordsToPixels(it->key+mWhiskerWidth*0.5, it->minimum)); // min bar
25750  result[1].setPoints(coordsToPixels(it->key-mWhiskerWidth*0.5, it->maximum), coordsToPixels(it->key+mWhiskerWidth*0.5, it->maximum)); // max bar
25751  return result;
25752 }
25753 /* end of 'src/plottables/plottable-statisticalbox.cpp' */
25754 
25755 
25756 /* including file 'src/plottables/plottable-colormap.cpp' */
25757 /* modified 2021-03-29T02:30:44, size 48149 */
25758 
25762 
25796 /* start of documentation of inline functions */
25797 
25804 /* end of documentation of inline functions */
25805 
25813 QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) :
25814  mKeySize(0),
25815  mValueSize(0),
25816  mKeyRange(keyRange),
25817  mValueRange(valueRange),
25818  mIsEmpty(true),
25819  mData(nullptr),
25820  mAlpha(nullptr),
25821  mDataModified(true)
25822 {
25824  fill(0);
25825 }
25826 
25828 {
25829  delete[] mData;
25830  delete[] mAlpha;
25831 }
25832 
25837  mKeySize(0),
25838  mValueSize(0),
25839  mIsEmpty(true),
25840  mData(nullptr),
25841  mAlpha(nullptr),
25842  mDataModified(true)
25843 {
25844  *this = other;
25845 }
25846 
25852 {
25853  if (&other != this)
25854  {
25855  const int keySize = other.keySize();
25856  const int valueSize = other.valueSize();
25857  if (!other.mAlpha && mAlpha)
25858  clearAlpha();
25860  if (other.mAlpha && !mAlpha)
25861  createAlpha(false);
25862  setRange(other.keyRange(), other.valueRange());
25863  if (!isEmpty())
25864  {
25865  memcpy(mData, other.mData, sizeof(mData[0])*size_t(keySize*valueSize));
25866  if (mAlpha)
25867  memcpy(mAlpha, other.mAlpha, sizeof(mAlpha[0])*size_t(keySize*valueSize));
25868  }
25869  mDataBounds = other.mDataBounds;
25870  mDataModified = true;
25871  }
25872  return *this;
25873 }
25874 
25875 /* undocumented getter */
25876 double QCPColorMapData::data(double key, double value)
25877 {
25878  int keyCell = int( (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5 );
25879  int valueCell = int( (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5 );
25880  if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
25881  return mData[valueCell*mKeySize + keyCell];
25882  else
25883  return 0;
25884 }
25885 
25886 /* undocumented getter */
25887 double QCPColorMapData::cell(int keyIndex, int valueIndex)
25888 {
25889  if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
25890  return mData[valueIndex*mKeySize + keyIndex];
25891  else
25892  return 0;
25893 }
25894 
25903 unsigned char QCPColorMapData::alpha(int keyIndex, int valueIndex)
25904 {
25905  if (mAlpha && keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
25906  return mAlpha[valueIndex*mKeySize + keyIndex];
25907  else
25908  return 255;
25909 }
25910 
25923 void QCPColorMapData::setSize(int keySize, int valueSize)
25924 {
25925  if (keySize != mKeySize || valueSize != mValueSize)
25926  {
25927  mKeySize = keySize;
25929  delete[] mData;
25930  mIsEmpty = mKeySize == 0 || mValueSize == 0;
25931  if (!mIsEmpty)
25932  {
25933 #ifdef __EXCEPTIONS
25934  try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message
25935 #endif
25936  mData = new double[size_t(mKeySize*mValueSize)];
25937 #ifdef __EXCEPTIONS
25938  } catch (...) { mData = nullptr; }
25939 #endif
25940  if (mData)
25941  fill(0);
25942  else
25943  qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize;
25944  } else
25945  mData = nullptr;
25946 
25947  if (mAlpha) // if we had an alpha map, recreate it with new size
25948  createAlpha();
25949 
25950  mDataModified = true;
25951  }
25952 }
25953 
25965 {
25967 }
25968 
25980 {
25982 }
25983 
25994 void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange)
25995 {
25998 }
25999 
26011 {
26012  mKeyRange = keyRange;
26013 }
26014 
26026 {
26028 }
26029 
26042 void QCPColorMapData::setData(double key, double value, double z)
26043 {
26044  int keyCell = int( (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5 );
26045  int valueCell = int( (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5 );
26046  if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize)
26047  {
26048  mData[valueCell*mKeySize + keyCell] = z;
26049  if (z < mDataBounds.lower)
26050  mDataBounds.lower = z;
26051  if (z > mDataBounds.upper)
26052  mDataBounds.upper = z;
26053  mDataModified = true;
26054  }
26055 }
26056 
26068 void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z)
26069 {
26070  if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
26071  {
26072  mData[valueIndex*mKeySize + keyIndex] = z;
26073  if (z < mDataBounds.lower)
26074  mDataBounds.lower = z;
26075  if (z > mDataBounds.upper)
26076  mDataBounds.upper = z;
26077  mDataModified = true;
26078  } else
26079  qDebug() << Q_FUNC_INFO << "index out of bounds:" << keyIndex << valueIndex;
26080 }
26081 
26097 void QCPColorMapData::setAlpha(int keyIndex, int valueIndex, unsigned char alpha)
26098 {
26099  if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize)
26100  {
26101  if (mAlpha || createAlpha())
26102  {
26103  mAlpha[valueIndex*mKeySize + keyIndex] = alpha;
26104  mDataModified = true;
26105  }
26106  } else
26107  qDebug() << Q_FUNC_INFO << "index out of bounds:" << keyIndex << valueIndex;
26108 }
26109 
26124 {
26125  if (mKeySize > 0 && mValueSize > 0)
26126  {
26127  double minHeight = mData[0];
26128  double maxHeight = mData[0];
26129  const int dataCount = mValueSize*mKeySize;
26130  for (int i=0; i<dataCount; ++i)
26131  {
26132  if (mData[i] > maxHeight)
26133  maxHeight = mData[i];
26134  if (mData[i] < minHeight)
26135  minHeight = mData[i];
26136  }
26137  mDataBounds.lower = minHeight;
26138  mDataBounds.upper = maxHeight;
26139  }
26140 }
26141 
26148 {
26149  setSize(0, 0);
26150 }
26151 
26156 {
26157  if (mAlpha)
26158  {
26159  delete[] mAlpha;
26160  mAlpha = nullptr;
26161  mDataModified = true;
26162  }
26163 }
26164 
26169 {
26170  const int dataCount = mValueSize*mKeySize;
26171  for (int i=0; i<dataCount; ++i)
26172  mData[i] = z;
26173  mDataBounds = QCPRange(z, z);
26174  mDataModified = true;
26175 }
26176 
26186 void QCPColorMapData::fillAlpha(unsigned char alpha)
26187 {
26188  if (mAlpha || createAlpha(false))
26189  {
26190  const int dataCount = mValueSize*mKeySize;
26191  for (int i=0; i<dataCount; ++i)
26192  mAlpha[i] = alpha;
26193  mDataModified = true;
26194  }
26195 }
26196 
26214 void QCPColorMapData::coordToCell(double key, double value, int *keyIndex, int *valueIndex) const
26215 {
26216  if (keyIndex)
26217  *keyIndex = int( (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5 );
26218  if (valueIndex)
26219  *valueIndex = int( (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5 );
26220 }
26221 
26237 void QCPColorMapData::cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const
26238 {
26239  if (key)
26240  *key = keyIndex/double(mKeySize-1)*(mKeyRange.upper-mKeyRange.lower)+mKeyRange.lower;
26241  if (value)
26242  *value = valueIndex/double(mValueSize-1)*(mValueRange.upper-mValueRange.lower)+mValueRange.lower;
26243 }
26244 
26258 bool QCPColorMapData::createAlpha(bool initializeOpaque)
26259 {
26260  clearAlpha();
26261  if (isEmpty())
26262  return false;
26263 
26264 #ifdef __EXCEPTIONS
26265  try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message
26266 #endif
26267  mAlpha = new unsigned char[size_t(mKeySize*mValueSize)];
26268 #ifdef __EXCEPTIONS
26269  } catch (...) { mAlpha = nullptr; }
26270 #endif
26271  if (mAlpha)
26272  {
26273  if (initializeOpaque)
26274  fillAlpha(255);
26275  return true;
26276  } else
26277  {
26278  qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize;
26279  return false;
26280  }
26281 }
26282 
26283 
26287 
26364 /* start documentation of inline functions */
26365 
26374 /* end documentation of inline functions */
26375 
26376 /* start documentation of signals */
26377 
26399 /* end documentation of signals */
26400 
26409  QCPAbstractPlottable(keyAxis, valueAxis),
26410  mDataScaleType(QCPAxis::stLinear),
26411  mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))),
26412  mGradient(QCPColorGradient::gpCold),
26413  mInterpolate(true),
26414  mTightBoundary(false),
26415  mMapImageInvalidated(true)
26416 {
26417 }
26418 
26420 {
26421  delete mMapData;
26422 }
26423 
26432 {
26433  if (mMapData == data)
26434  {
26435  qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast<quintptr>(data);
26436  return;
26437  }
26438  if (copy)
26439  {
26440  *mMapData = *data;
26441  } else
26442  {
26443  delete mMapData;
26444  mMapData = data;
26445  }
26446  mMapImageInvalidated = true;
26447 }
26448 
26457 void QCPColorMap::setDataRange(const QCPRange &dataRange)
26458 {
26459  if (!QCPRange::validRange(dataRange)) return;
26461  {
26464  else
26466  mMapImageInvalidated = true;
26468  }
26469 }
26470 
26477 {
26478  if (mDataScaleType != scaleType)
26479  {
26480  mDataScaleType = scaleType;
26481  mMapImageInvalidated = true;
26485  }
26486 }
26487 
26500 {
26501  if (mGradient != gradient)
26502  {
26503  mGradient = gradient;
26504  mMapImageInvalidated = true;
26505  emit gradientChanged(mGradient);
26506  }
26507 }
26508 
26516 {
26517  mInterpolate = enabled;
26518  mMapImageInvalidated = true; // because oversampling factors might need to change
26519 }
26520 
26533 {
26534  mTightBoundary = enabled;
26535 }
26536 
26552 {
26553  if (mColorScale) // unconnect signals from old color scale
26554  {
26555  disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
26556  disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType)));
26557  disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
26558  disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
26559  disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
26560  disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType)));
26561  }
26563  if (mColorScale) // connect signals to new color scale
26564  {
26565  setGradient(mColorScale.data()->gradient());
26566  setDataRange(mColorScale.data()->dataRange());
26567  setDataScaleType(mColorScale.data()->dataScaleType());
26568  connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange)));
26570  connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient)));
26571  connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange)));
26572  connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient)));
26574  }
26575 }
26576 
26597 void QCPColorMap::rescaleDataRange(bool recalculateDataBounds)
26598 {
26599  if (recalculateDataBounds)
26602 }
26603 
26618 void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize)
26619 {
26620  if (mMapImage.isNull() && !data()->isEmpty())
26621  updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet)
26622 
26623  if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again
26624  {
26625  bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
26626  bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
26627  mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode);
26628  }
26629 }
26630 
26631 /* inherits documentation from base class */
26632 double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
26633 {
26634  Q_UNUSED(details)
26635  if ((onlySelectable && mSelectable == QCP::stNone) || mMapData->isEmpty())
26636  return -1;
26637  if (!mKeyAxis || !mValueAxis)
26638  return -1;
26639 
26640  if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
26641  {
26642  double posKey, posValue;
26643  pixelsToCoords(pos, posKey, posValue);
26644  if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue))
26645  {
26646  if (details)
26647  details->setValue(QCPDataSelection(QCPDataRange(0, 1))); // temporary solution, to facilitate whole-plottable selection. Replace in future version with segmented 2D selection.
26648  return mParentPlot->selectionTolerance()*0.99;
26649  }
26650  }
26651  return -1;
26652 }
26653 
26654 /* inherits documentation from base class */
26655 QCPRange QCPColorMap::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
26656 {
26657  foundRange = true;
26658  QCPRange result = mMapData->keyRange();
26659  result.normalize();
26660  if (inSignDomain == QCP::sdPositive)
26661  {
26662  if (result.lower <= 0 && result.upper > 0)
26663  result.lower = result.upper*1e-3;
26664  else if (result.lower <= 0 && result.upper <= 0)
26665  foundRange = false;
26666  } else if (inSignDomain == QCP::sdNegative)
26667  {
26668  if (result.upper >= 0 && result.lower < 0)
26669  result.upper = result.lower*1e-3;
26670  else if (result.upper >= 0 && result.lower >= 0)
26671  foundRange = false;
26672  }
26673  return result;
26674 }
26675 
26676 /* inherits documentation from base class */
26677 QCPRange QCPColorMap::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
26678 {
26679  if (inKeyRange != QCPRange())
26680  {
26681  if (mMapData->keyRange().upper < inKeyRange.lower || mMapData->keyRange().lower > inKeyRange.upper)
26682  {
26683  foundRange = false;
26684  return {};
26685  }
26686  }
26687 
26688  foundRange = true;
26689  QCPRange result = mMapData->valueRange();
26690  result.normalize();
26691  if (inSignDomain == QCP::sdPositive)
26692  {
26693  if (result.lower <= 0 && result.upper > 0)
26694  result.lower = result.upper*1e-3;
26695  else if (result.lower <= 0 && result.upper <= 0)
26696  foundRange = false;
26697  } else if (inSignDomain == QCP::sdNegative)
26698  {
26699  if (result.upper >= 0 && result.lower < 0)
26700  result.upper = result.lower*1e-3;
26701  else if (result.upper >= 0 && result.lower >= 0)
26702  foundRange = false;
26703  }
26704  return result;
26705 }
26706 
26722 {
26723  QCPAxis *keyAxis = mKeyAxis.data();
26724  if (!keyAxis) return;
26725  if (mMapData->isEmpty()) return;
26726 
26727  const QImage::Format format = QImage::Format_ARGB32_Premultiplied;
26728  const int keySize = mMapData->keySize();
26729  const int valueSize = mMapData->valueSize();
26730  int keyOversamplingFactor = mInterpolate ? 1 : int(1.0+100.0/double(keySize)); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on
26731  int valueOversamplingFactor = mInterpolate ? 1 : int(1.0+100.0/double(valueSize)); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on
26732 
26733  // resize mMapImage to correct dimensions including possible oversampling factors, according to key/value axes orientation:
26734  if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.width() != keySize*keyOversamplingFactor || mMapImage.height() != valueSize*valueOversamplingFactor))
26735  mMapImage = QImage(QSize(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor), format);
26736  else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.width() != valueSize*valueOversamplingFactor || mMapImage.height() != keySize*keyOversamplingFactor))
26737  mMapImage = QImage(QSize(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor), format);
26738 
26739  if (mMapImage.isNull())
26740  {
26741  qDebug() << Q_FUNC_INFO << "Couldn't create map image (possibly too large for memory)";
26742  mMapImage = QImage(QSize(10, 10), format);
26743  mMapImage.fill(Qt::black);
26744  } else
26745  {
26746  QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. Either the final mMapImage, or if we need oversampling, mUndersampledMapImage
26747  if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1)
26748  {
26749  // resize undersampled map image to actual key/value cell sizes:
26750  if (keyAxis->orientation() == Qt::Horizontal && (mUndersampledMapImage.width() != keySize || mUndersampledMapImage.height() != valueSize))
26751  mUndersampledMapImage = QImage(QSize(keySize, valueSize), format);
26752  else if (keyAxis->orientation() == Qt::Vertical && (mUndersampledMapImage.width() != valueSize || mUndersampledMapImage.height() != keySize))
26753  mUndersampledMapImage = QImage(QSize(valueSize, keySize), format);
26754  localMapImage = &mUndersampledMapImage; // make the colorization run on the undersampled image
26755  } else if (!mUndersampledMapImage.isNull())
26756  mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size has changed) but mUndersampledMapImage still has nonzero size, free it
26757 
26758  const double *rawData = mMapData->mData;
26759  const unsigned char *rawAlpha = mMapData->mAlpha;
26760  if (keyAxis->orientation() == Qt::Horizontal)
26761  {
26762  const int lineCount = valueSize;
26763  const int rowCount = keySize;
26764  for (int line=0; line<lineCount; ++line)
26765  {
26766  QRgb* pixels = reinterpret_cast<QRgb*>(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
26767  if (rawAlpha)
26768  mGradient.colorize(rawData+line*rowCount, rawAlpha+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic);
26769  else
26770  mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic);
26771  }
26772  } else // keyAxis->orientation() == Qt::Vertical
26773  {
26774  const int lineCount = keySize;
26775  const int rowCount = valueSize;
26776  for (int line=0; line<lineCount; ++line)
26777  {
26778  QRgb* pixels = reinterpret_cast<QRgb*>(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system)
26779  if (rawAlpha)
26780  mGradient.colorize(rawData+line, rawAlpha+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic);
26781  else
26782  mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic);
26783  }
26784  }
26785 
26786  if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1)
26787  {
26788  if (keyAxis->orientation() == Qt::Horizontal)
26789  mMapImage = mUndersampledMapImage.scaled(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation);
26790  else
26791  mMapImage = mUndersampledMapImage.scaled(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation);
26792  }
26793  }
26794  mMapData->mDataModified = false;
26795  mMapImageInvalidated = false;
26796 }
26797 
26798 /* inherits documentation from base class */
26800 {
26801  if (mMapData->isEmpty()) return;
26802  if (!mKeyAxis || !mValueAxis) return;
26804 
26806  updateMapImage();
26807 
26808  // use buffer if painting vectorized (PDF):
26809  const bool useBuffer = painter->modes().testFlag(QCPPainter::pmVectorized);
26810  QCPPainter *localPainter = painter; // will be redirected to paint on mapBuffer if painting vectorized
26811  QRectF mapBufferTarget; // the rect in absolute widget coordinates where the visible map portion/buffer will end up in
26812  QPixmap mapBuffer;
26813  if (useBuffer)
26814  {
26815  const double mapBufferPixelRatio = 3; // factor by which DPI is increased in embedded bitmaps
26816  mapBufferTarget = painter->clipRegion().boundingRect();
26817  mapBuffer = QPixmap((mapBufferTarget.size()*mapBufferPixelRatio).toSize());
26818  mapBuffer.fill(Qt::transparent);
26819  localPainter = new QCPPainter(&mapBuffer);
26820  localPainter->scale(mapBufferPixelRatio, mapBufferPixelRatio);
26821  localPainter->translate(-mapBufferTarget.topLeft());
26822  }
26823 
26824  QRectF imageRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower),
26826  // extend imageRect to contain outer halves/quarters of bordering/cornering pixels (cells are centered on map range boundary):
26827  double halfCellWidth = 0; // in pixels
26828  double halfCellHeight = 0; // in pixels
26829  if (keyAxis()->orientation() == Qt::Horizontal)
26830  {
26831  if (mMapData->keySize() > 1)
26832  halfCellWidth = 0.5*imageRect.width()/double(mMapData->keySize()-1);
26833  if (mMapData->valueSize() > 1)
26834  halfCellHeight = 0.5*imageRect.height()/double(mMapData->valueSize()-1);
26835  } else // keyAxis orientation is Qt::Vertical
26836  {
26837  if (mMapData->keySize() > 1)
26838  halfCellHeight = 0.5*imageRect.height()/double(mMapData->keySize()-1);
26839  if (mMapData->valueSize() > 1)
26840  halfCellWidth = 0.5*imageRect.width()/double(mMapData->valueSize()-1);
26841  }
26842  imageRect.adjust(-halfCellWidth, -halfCellHeight, halfCellWidth, halfCellHeight);
26843  const bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed();
26844  const bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed();
26845  const bool smoothBackup = localPainter->renderHints().testFlag(QPainter::SmoothPixmapTransform);
26846  localPainter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate);
26847  QRegion clipBackup;
26848  if (mTightBoundary)
26849  {
26850  clipBackup = localPainter->clipRegion();
26851  QRectF tightClipRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower),
26853  localPainter->setClipRect(tightClipRect, Qt::IntersectClip);
26854  }
26855  localPainter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY));
26856  if (mTightBoundary)
26857  localPainter->setClipRegion(clipBackup);
26858  localPainter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup);
26859 
26860  if (useBuffer) // localPainter painted to mapBuffer, so now draw buffer with original painter
26861  {
26862  delete localPainter;
26863  painter->drawPixmap(mapBufferTarget.toRect(), mapBuffer);
26864  }
26865 }
26866 
26867 /* inherits documentation from base class */
26868 void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
26869 {
26871  // draw map thumbnail:
26872  if (!mLegendIcon.isNull())
26873  {
26874  QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
26875  QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height());
26876  iconRect.moveCenter(rect.center());
26877  painter->drawPixmap(iconRect.topLeft(), scaledIcon);
26878  }
26879  /*
26880  // draw frame:
26881  painter->setBrush(Qt::NoBrush);
26882  painter->setPen(Qt::black);
26883  painter->drawRect(rect.adjusted(1, 1, 0, 0));
26884  */
26885 }
26886 /* end of 'src/plottables/plottable-colormap.cpp' */
26887 
26888 
26889 /* including file 'src/plottables/plottable-financial.cpp' */
26890 /* modified 2021-03-29T02:30:44, size 42914 */
26891 
26895 
26913 /* start documentation of inline functions */
26914 
26964 /* end documentation of inline functions */
26965 
26970  key(0),
26971  open(0),
26972  high(0),
26973  low(0),
26974  close(0)
26975 {
26976 }
26977 
26981 QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) :
26982  key(key),
26983  open(open),
26984  high(high),
26985  low(low),
26986  close(close)
26987 {
26988 }
26989 
26990 
26994 
27044 /* start of documentation of inline functions */
27045 
27053 /* end of documentation of inline functions */
27054 
27066  QCPAbstractPlottable1D<QCPFinancialData>(keyAxis, valueAxis),
27067  mChartStyle(csCandlestick),
27068  mWidth(0.5),
27069  mWidthType(wtPlotCoords),
27070  mTwoColored(true),
27071  mBrushPositive(QBrush(QColor(50, 160, 0))),
27072  mBrushNegative(QBrush(QColor(180, 0, 15))),
27073  mPenPositive(QPen(QColor(40, 150, 0))),
27074  mPenNegative(QPen(QColor(170, 5, 5)))
27075 {
27076  mSelectionDecorator->setBrush(QBrush(QColor(160, 160, 255)));
27077 }
27078 
27080 {
27081 }
27082 
27098 void QCPFinancial::setData(QSharedPointer<QCPFinancialDataContainer> data)
27099 {
27100  mDataContainer = data;
27101 }
27102 
27114 void QCPFinancial::setData(const QVector<double> &keys, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close, bool alreadySorted)
27115 {
27116  mDataContainer->clear();
27117  addData(keys, open, high, low, close, alreadySorted);
27118 }
27119 
27124 {
27125  mChartStyle = style;
27126 }
27127 
27133 void QCPFinancial::setWidth(double width)
27134 {
27135  mWidth = width;
27136 }
27137 
27147 {
27149 }
27150 
27160 void QCPFinancial::setTwoColored(bool twoColored)
27161 {
27163 }
27164 
27174 void QCPFinancial::setBrushPositive(const QBrush &brush)
27175 {
27177 }
27178 
27188 void QCPFinancial::setBrushNegative(const QBrush &brush)
27189 {
27191 }
27192 
27202 void QCPFinancial::setPenPositive(const QPen &pen)
27203 {
27204  mPenPositive = pen;
27205 }
27206 
27216 void QCPFinancial::setPenNegative(const QPen &pen)
27217 {
27218  mPenNegative = pen;
27219 }
27220 
27235 void QCPFinancial::addData(const QVector<double> &keys, const QVector<double> &open, const QVector<double> &high, const QVector<double> &low, const QVector<double> &close, bool alreadySorted)
27236 {
27237  if (keys.size() != open.size() || open.size() != high.size() || high.size() != low.size() || low.size() != close.size() || close.size() != keys.size())
27238  qDebug() << Q_FUNC_INFO << "keys, open, high, low, close have different sizes:" << keys.size() << open.size() << high.size() << low.size() << close.size();
27239  const int n = qMin(keys.size(), qMin(open.size(), qMin(high.size(), qMin(low.size(), close.size()))));
27240  QVector<QCPFinancialData> tempData(n);
27241  QVector<QCPFinancialData>::iterator it = tempData.begin();
27242  const QVector<QCPFinancialData>::iterator itEnd = tempData.end();
27243  int i = 0;
27244  while (it != itEnd)
27245  {
27246  it->key = keys[i];
27247  it->open = open[i];
27248  it->high = high[i];
27249  it->low = low[i];
27250  it->close = close[i];
27251  ++it;
27252  ++i;
27253  }
27254  mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write
27255 }
27256 
27267 void QCPFinancial::addData(double key, double open, double high, double low, double close)
27268 {
27269  mDataContainer->add(QCPFinancialData(key, open, high, low, close));
27270 }
27271 
27275 QCPDataSelection QCPFinancial::selectTestRect(const QRectF &rect, bool onlySelectable) const
27276 {
27277  QCPDataSelection result;
27278  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
27279  return result;
27280  if (!mKeyAxis || !mValueAxis)
27281  return result;
27282 
27283  QCPFinancialDataContainer::const_iterator visibleBegin, visibleEnd;
27284  getVisibleDataBounds(visibleBegin, visibleEnd);
27285 
27286  for (QCPFinancialDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
27287  {
27288  if (rect.intersects(selectionHitBox(it)))
27289  result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false);
27290  }
27291  result.simplify();
27292  return result;
27293 }
27294 
27303 double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
27304 {
27305  Q_UNUSED(details)
27306  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
27307  return -1;
27308  if (!mKeyAxis || !mValueAxis)
27309  return -1;
27310 
27311  if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
27312  {
27313  // get visible data range:
27314  QCPFinancialDataContainer::const_iterator visibleBegin, visibleEnd;
27315  QCPFinancialDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd();
27316  getVisibleDataBounds(visibleBegin, visibleEnd);
27317  // perform select test according to configured style:
27318  double result = -1;
27319  switch (mChartStyle)
27320  {
27321  case QCPFinancial::csOhlc:
27322  result = ohlcSelectTest(pos, visibleBegin, visibleEnd, closestDataPoint); break;
27324  result = candlestickSelectTest(pos, visibleBegin, visibleEnd, closestDataPoint); break;
27325  }
27326  if (details)
27327  {
27328  int pointIndex = int(closestDataPoint-mDataContainer->constBegin());
27329  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
27330  }
27331  return result;
27332  }
27333 
27334  return -1;
27335 }
27336 
27337 /* inherits documentation from base class */
27338 QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
27339 {
27340  QCPRange range = mDataContainer->keyRange(foundRange, inSignDomain);
27341  // determine exact range by including width of bars/flags:
27342  if (foundRange)
27343  {
27344  if (inSignDomain != QCP::sdPositive || range.lower-mWidth*0.5 > 0)
27345  range.lower -= mWidth*0.5;
27346  if (inSignDomain != QCP::sdNegative || range.upper+mWidth*0.5 < 0)
27347  range.upper += mWidth*0.5;
27348  }
27349  return range;
27350 }
27351 
27352 /* inherits documentation from base class */
27353 QCPRange QCPFinancial::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
27354 {
27355  return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
27356 }
27357 
27372 QCPFinancialDataContainer QCPFinancial::timeSeriesToOhlc(const QVector<double> &time, const QVector<double> &value, double timeBinSize, double timeBinOffset)
27373 {
27375  int count = qMin(time.size(), value.size());
27376  if (count == 0)
27377  return QCPFinancialDataContainer();
27378 
27379  QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first());
27380  int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5);
27381  for (int i=0; i<count; ++i)
27382  {
27383  int index = qFloor((time.at(i)-timeBinOffset)/timeBinSize+0.5);
27384  if (currentBinIndex == index) // data point still in current bin, extend high/low:
27385  {
27386  if (value.at(i) < currentBinData.low) currentBinData.low = value.at(i);
27387  if (value.at(i) > currentBinData.high) currentBinData.high = value.at(i);
27388  if (i == count-1) // last data point is in current bin, finalize bin:
27389  {
27390  currentBinData.close = value.at(i);
27391  currentBinData.key = timeBinOffset+(index)*timeBinSize;
27392  data.add(currentBinData);
27393  }
27394  } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map:
27395  {
27396  // finalize current bin:
27397  currentBinData.close = value.at(i-1);
27398  currentBinData.key = timeBinOffset+(index-1)*timeBinSize;
27399  data.add(currentBinData);
27400  // start next bin:
27401  currentBinIndex = index;
27402  currentBinData.open = value.at(i);
27403  currentBinData.high = value.at(i);
27404  currentBinData.low = value.at(i);
27405  }
27406  }
27407 
27408  return data;
27409 }
27410 
27411 /* inherits documentation from base class */
27413 {
27414  // get visible data range:
27415  QCPFinancialDataContainer::const_iterator visibleBegin, visibleEnd;
27416  getVisibleDataBounds(visibleBegin, visibleEnd);
27417 
27418  // loop over and draw segments of unselected/selected data:
27419  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
27420  getDataSegments(selectedSegments, unselectedSegments);
27421  allSegments << unselectedSegments << selectedSegments;
27422  for (int i=0; i<allSegments.size(); ++i)
27423  {
27424  bool isSelectedSegment = i >= unselectedSegments.size();
27425  QCPFinancialDataContainer::const_iterator begin = visibleBegin;
27427  mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
27428  if (begin == end)
27429  continue;
27430 
27431  // draw data segment according to configured style:
27432  switch (mChartStyle)
27433  {
27434  case QCPFinancial::csOhlc:
27435  drawOhlcPlot(painter, begin, end, isSelectedSegment); break;
27437  drawCandlestickPlot(painter, begin, end, isSelectedSegment); break;
27438  }
27439  }
27440 
27441  // draw other selection decoration that isn't just line/scatter pens and brushes:
27442  if (mSelectionDecorator)
27444 }
27445 
27446 /* inherits documentation from base class */
27447 void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
27448 {
27449  painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing
27450  if (mChartStyle == csOhlc)
27451  {
27452  if (mTwoColored)
27453  {
27454  // draw upper left half icon with positive color:
27455  painter->setBrush(mBrushPositive);
27456  painter->setPen(mPenPositive);
27457  painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
27458  painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27459  painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
27460  painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
27461  // draw bottom right half icon with negative color:
27462  painter->setBrush(mBrushNegative);
27463  painter->setPen(mPenNegative);
27464  painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
27465  painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27466  painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
27467  painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
27468  } else
27469  {
27470  painter->setBrush(mBrush);
27471  painter->setPen(mPen);
27472  painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27473  painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
27474  painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
27475  }
27476  } else if (mChartStyle == csCandlestick)
27477  {
27478  if (mTwoColored)
27479  {
27480  // draw upper left half icon with positive color:
27481  painter->setBrush(mBrushPositive);
27482  painter->setPen(mPenPositive);
27483  painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
27484  painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
27485  painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27486  painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
27487  // draw bottom right half icon with negative color:
27488  painter->setBrush(mBrushNegative);
27489  painter->setPen(mPenNegative);
27490  painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
27491  painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
27492  painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27493  painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
27494  } else
27495  {
27496  painter->setBrush(mBrush);
27497  painter->setPen(mPen);
27498  painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
27499  painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27500  painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
27501  }
27502  }
27503 }
27504 
27512 {
27513  QCPAxis *keyAxis = mKeyAxis.data();
27514  QCPAxis *valueAxis = mValueAxis.data();
27515  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
27516 
27517  if (keyAxis->orientation() == Qt::Horizontal)
27518  {
27519  for (QCPFinancialDataContainer::const_iterator it = begin; it != end; ++it)
27520  {
27521  if (isSelected && mSelectionDecorator)
27522  mSelectionDecorator->applyPen(painter);
27523  else if (mTwoColored)
27524  painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative);
27525  else
27526  painter->setPen(mPen);
27527  double keyPixel = keyAxis->coordToPixel(it->key);
27528  double openPixel = valueAxis->coordToPixel(it->open);
27529  double closePixel = valueAxis->coordToPixel(it->close);
27530  // draw backbone:
27531  painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it->high)), QPointF(keyPixel, valueAxis->coordToPixel(it->low)));
27532  // draw open:
27533  double pixelWidth = getPixelWidth(it->key, keyPixel); // sign of this makes sure open/close are on correct sides
27534  painter->drawLine(QPointF(keyPixel-pixelWidth, openPixel), QPointF(keyPixel, openPixel));
27535  // draw close:
27536  painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+pixelWidth, closePixel));
27537  }
27538  } else
27539  {
27540  for (QCPFinancialDataContainer::const_iterator it = begin; it != end; ++it)
27541  {
27542  if (isSelected && mSelectionDecorator)
27543  mSelectionDecorator->applyPen(painter);
27544  else if (mTwoColored)
27545  painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative);
27546  else
27547  painter->setPen(mPen);
27548  double keyPixel = keyAxis->coordToPixel(it->key);
27549  double openPixel = valueAxis->coordToPixel(it->open);
27550  double closePixel = valueAxis->coordToPixel(it->close);
27551  // draw backbone:
27552  painter->drawLine(QPointF(valueAxis->coordToPixel(it->high), keyPixel), QPointF(valueAxis->coordToPixel(it->low), keyPixel));
27553  // draw open:
27554  double pixelWidth = getPixelWidth(it->key, keyPixel); // sign of this makes sure open/close are on correct sides
27555  painter->drawLine(QPointF(openPixel, keyPixel-pixelWidth), QPointF(openPixel, keyPixel));
27556  // draw close:
27557  painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+pixelWidth));
27558  }
27559  }
27560 }
27561 
27569 {
27570  QCPAxis *keyAxis = mKeyAxis.data();
27571  QCPAxis *valueAxis = mValueAxis.data();
27572  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
27573 
27574  if (keyAxis->orientation() == Qt::Horizontal)
27575  {
27576  for (QCPFinancialDataContainer::const_iterator it = begin; it != end; ++it)
27577  {
27578  if (isSelected && mSelectionDecorator)
27579  {
27580  mSelectionDecorator->applyPen(painter);
27581  mSelectionDecorator->applyBrush(painter);
27582  } else if (mTwoColored)
27583  {
27584  painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative);
27585  painter->setBrush(it->close >= it->open ? mBrushPositive : mBrushNegative);
27586  } else
27587  {
27588  painter->setPen(mPen);
27589  painter->setBrush(mBrush);
27590  }
27591  double keyPixel = keyAxis->coordToPixel(it->key);
27592  double openPixel = valueAxis->coordToPixel(it->open);
27593  double closePixel = valueAxis->coordToPixel(it->close);
27594  // draw high:
27595  painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it->high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it->open, it->close))));
27596  // draw low:
27597  painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it->low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it->open, it->close))));
27598  // draw open-close box:
27599  double pixelWidth = getPixelWidth(it->key, keyPixel);
27600  painter->drawRect(QRectF(QPointF(keyPixel-pixelWidth, closePixel), QPointF(keyPixel+pixelWidth, openPixel)));
27601  }
27602  } else // keyAxis->orientation() == Qt::Vertical
27603  {
27604  for (QCPFinancialDataContainer::const_iterator it = begin; it != end; ++it)
27605  {
27606  if (isSelected && mSelectionDecorator)
27607  {
27608  mSelectionDecorator->applyPen(painter);
27609  mSelectionDecorator->applyBrush(painter);
27610  } else if (mTwoColored)
27611  {
27612  painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative);
27613  painter->setBrush(it->close >= it->open ? mBrushPositive : mBrushNegative);
27614  } else
27615  {
27616  painter->setPen(mPen);
27617  painter->setBrush(mBrush);
27618  }
27619  double keyPixel = keyAxis->coordToPixel(it->key);
27620  double openPixel = valueAxis->coordToPixel(it->open);
27621  double closePixel = valueAxis->coordToPixel(it->close);
27622  // draw high:
27623  painter->drawLine(QPointF(valueAxis->coordToPixel(it->high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it->open, it->close)), keyPixel));
27624  // draw low:
27625  painter->drawLine(QPointF(valueAxis->coordToPixel(it->low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it->open, it->close)), keyPixel));
27626  // draw open-close box:
27627  double pixelWidth = getPixelWidth(it->key, keyPixel);
27628  painter->drawRect(QRectF(QPointF(closePixel, keyPixel-pixelWidth), QPointF(openPixel, keyPixel+pixelWidth)));
27629  }
27630  }
27631 }
27632 
27645 double QCPFinancial::getPixelWidth(double key, double keyPixel) const
27646 {
27647  double result = 0;
27648  switch (mWidthType)
27649  {
27650  case wtAbsolute:
27651  {
27652  if (mKeyAxis)
27653  result = mWidth*0.5*mKeyAxis.data()->pixelOrientation();
27654  break;
27655  }
27656  case wtAxisRectRatio:
27657  {
27658  if (mKeyAxis && mKeyAxis.data()->axisRect())
27659  {
27660  if (mKeyAxis.data()->orientation() == Qt::Horizontal)
27661  result = mKeyAxis.data()->axisRect()->width()*mWidth*0.5*mKeyAxis.data()->pixelOrientation();
27662  else
27663  result = mKeyAxis.data()->axisRect()->height()*mWidth*0.5*mKeyAxis.data()->pixelOrientation();
27664  } else
27665  qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined";
27666  break;
27667  }
27668  case wtPlotCoords:
27669  {
27670  if (mKeyAxis)
27671  result = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel;
27672  else
27673  qDebug() << Q_FUNC_INFO << "No key axis defined";
27674  break;
27675  }
27676  }
27677  return result;
27678 }
27679 
27689 {
27690  closestDataPoint = mDataContainer->constEnd();
27691  QCPAxis *keyAxis = mKeyAxis.data();
27692  QCPAxis *valueAxis = mValueAxis.data();
27693  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
27694 
27695  double minDistSqr = (std::numeric_limits<double>::max)();
27696  if (keyAxis->orientation() == Qt::Horizontal)
27697  {
27698  for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it)
27699  {
27700  double keyPixel = keyAxis->coordToPixel(it->key);
27701  // calculate distance to backbone:
27702  double currentDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(keyPixel, valueAxis->coordToPixel(it->high)), QCPVector2D(keyPixel, valueAxis->coordToPixel(it->low)));
27703  if (currentDistSqr < minDistSqr)
27704  {
27705  minDistSqr = currentDistSqr;
27706  closestDataPoint = it;
27707  }
27708  }
27709  } else // keyAxis->orientation() == Qt::Vertical
27710  {
27711  for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it)
27712  {
27713  double keyPixel = keyAxis->coordToPixel(it->key);
27714  // calculate distance to backbone:
27715  double currentDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(valueAxis->coordToPixel(it->high), keyPixel), QCPVector2D(valueAxis->coordToPixel(it->low), keyPixel));
27716  if (currentDistSqr < minDistSqr)
27717  {
27718  minDistSqr = currentDistSqr;
27719  closestDataPoint = it;
27720  }
27721  }
27722  }
27723  return qSqrt(minDistSqr);
27724 }
27725 
27736 {
27737  closestDataPoint = mDataContainer->constEnd();
27738  QCPAxis *keyAxis = mKeyAxis.data();
27739  QCPAxis *valueAxis = mValueAxis.data();
27740  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; }
27741 
27742  double minDistSqr = (std::numeric_limits<double>::max)();
27743  if (keyAxis->orientation() == Qt::Horizontal)
27744  {
27745  for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it)
27746  {
27747  double currentDistSqr;
27748  // determine whether pos is in open-close-box:
27749  QCPRange boxKeyRange(it->key-mWidth*0.5, it->key+mWidth*0.5);
27750  QCPRange boxValueRange(it->close, it->open);
27751  double posKey, posValue;
27752  pixelsToCoords(pos, posKey, posValue);
27753  if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
27754  {
27755  currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
27756  } else
27757  {
27758  // calculate distance to high/low lines:
27759  double keyPixel = keyAxis->coordToPixel(it->key);
27760  double highLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(keyPixel, valueAxis->coordToPixel(it->high)), QCPVector2D(keyPixel, valueAxis->coordToPixel(qMax(it->open, it->close))));
27761  double lowLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(keyPixel, valueAxis->coordToPixel(it->low)), QCPVector2D(keyPixel, valueAxis->coordToPixel(qMin(it->open, it->close))));
27762  currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
27763  }
27764  if (currentDistSqr < minDistSqr)
27765  {
27766  minDistSqr = currentDistSqr;
27767  closestDataPoint = it;
27768  }
27769  }
27770  } else // keyAxis->orientation() == Qt::Vertical
27771  {
27772  for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it)
27773  {
27774  double currentDistSqr;
27775  // determine whether pos is in open-close-box:
27776  QCPRange boxKeyRange(it->key-mWidth*0.5, it->key+mWidth*0.5);
27777  QCPRange boxValueRange(it->close, it->open);
27778  double posKey, posValue;
27779  pixelsToCoords(pos, posKey, posValue);
27780  if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box
27781  {
27782  currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99;
27783  } else
27784  {
27785  // calculate distance to high/low lines:
27786  double keyPixel = keyAxis->coordToPixel(it->key);
27787  double highLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(valueAxis->coordToPixel(it->high), keyPixel), QCPVector2D(valueAxis->coordToPixel(qMax(it->open, it->close)), keyPixel));
27788  double lowLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(valueAxis->coordToPixel(it->low), keyPixel), QCPVector2D(valueAxis->coordToPixel(qMin(it->open, it->close)), keyPixel));
27789  currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
27790  }
27791  if (currentDistSqr < minDistSqr)
27792  {
27793  minDistSqr = currentDistSqr;
27794  closestDataPoint = it;
27795  }
27796  }
27797  }
27798  return qSqrt(minDistSqr);
27799 }
27800 
27816 {
27817  if (!mKeyAxis)
27818  {
27819  qDebug() << Q_FUNC_INFO << "invalid key axis";
27820  begin = mDataContainer->constEnd();
27821  end = mDataContainer->constEnd();
27822  return;
27823  }
27824  begin = mDataContainer->findBegin(mKeyAxis.data()->range().lower-mWidth*0.5); // subtract half width of ohlc/candlestick to include partially visible data points
27825  end = mDataContainer->findEnd(mKeyAxis.data()->range().upper+mWidth*0.5); // add half width of ohlc/candlestick to include partially visible data points
27826 }
27827 
27834 {
27835  QCPAxis *keyAxis = mKeyAxis.data();
27836  QCPAxis *valueAxis = mValueAxis.data();
27837  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; }
27838 
27839  double keyPixel = keyAxis->coordToPixel(it->key);
27840  double highPixel = valueAxis->coordToPixel(it->high);
27841  double lowPixel = valueAxis->coordToPixel(it->low);
27842  double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it->key-mWidth*0.5);
27843  if (keyAxis->orientation() == Qt::Horizontal)
27844  return QRectF(keyPixel-keyWidthPixels, highPixel, keyWidthPixels*2, lowPixel-highPixel).normalized();
27845  else
27846  return QRectF(highPixel, keyPixel-keyWidthPixels, lowPixel-highPixel, keyWidthPixels*2).normalized();
27847 }
27848 /* end of 'src/plottables/plottable-financial.cpp' */
27849 
27850 
27851 /* including file 'src/plottables/plottable-errorbar.cpp' */
27852 /* modified 2021-03-29T02:30:44, size 37679 */
27853 
27857 
27877  errorMinus(0),
27878  errorPlus(0)
27879 {
27880 }
27881 
27886  errorMinus(error),
27887  errorPlus(error)
27888 {
27889 }
27890 
27895 QCPErrorBarsData::QCPErrorBarsData(double errorMinus, double errorPlus) :
27896  errorMinus(errorMinus),
27897  errorPlus(errorPlus)
27898 {
27899 }
27900 
27901 
27905 
27935 /* start of documentation of inline functions */
27936 
27944 /* end of documentation of inline functions */
27945 
27960  QCPAbstractPlottable(keyAxis, valueAxis),
27961  mDataContainer(new QVector<QCPErrorBarsData>),
27962  mErrorType(etValueError),
27963  mWhiskerWidth(9),
27964  mSymbolGap(10)
27965 {
27966  setPen(QPen(Qt::black, 0));
27967  setBrush(Qt::NoBrush);
27968 }
27969 
27971 {
27972 }
27973 
27992 void QCPErrorBars::setData(QSharedPointer<QCPErrorBarsDataContainer> data)
27993 {
27994  mDataContainer = data;
27995 }
27996 
28006 void QCPErrorBars::setData(const QVector<double> &error)
28007 {
28008  mDataContainer->clear();
28009  addData(error);
28010 }
28011 
28022 void QCPErrorBars::setData(const QVector<double> &errorMinus, const QVector<double> &errorPlus)
28023 {
28024  mDataContainer->clear();
28025  addData(errorMinus, errorPlus);
28026 }
28027 
28043 {
28044  if (plottable && qobject_cast<QCPErrorBars*>(plottable))
28045  {
28046  mDataPlottable = nullptr;
28047  qDebug() << Q_FUNC_INFO << "can't set another QCPErrorBars instance as data plottable";
28048  return;
28049  }
28050  if (plottable && !plottable->interface1D())
28051  {
28052  mDataPlottable = nullptr;
28053  qDebug() << Q_FUNC_INFO << "passed plottable doesn't implement 1d interface, can't associate with QCPErrorBars";
28054  return;
28055  }
28056 
28057  mDataPlottable = plottable;
28058 }
28059 
28065 {
28066  mErrorType = type;
28067 }
28068 
28074 {
28075  mWhiskerWidth = pixels;
28076 }
28077 
28083 void QCPErrorBars::setSymbolGap(double pixels)
28084 {
28085  mSymbolGap = pixels;
28086 }
28087 
28097 void QCPErrorBars::addData(const QVector<double> &error)
28098 {
28099  addData(error, error);
28100 }
28101 
28112 void QCPErrorBars::addData(const QVector<double> &errorMinus, const QVector<double> &errorPlus)
28113 {
28114  if (errorMinus.size() != errorPlus.size())
28115  qDebug() << Q_FUNC_INFO << "minus and plus error vectors have different sizes:" << errorMinus.size() << errorPlus.size();
28116  const int n = qMin(errorMinus.size(), errorPlus.size());
28117  mDataContainer->reserve(n);
28118  for (int i=0; i<n; ++i)
28119  mDataContainer->append(QCPErrorBarsData(errorMinus.at(i), errorPlus.at(i)));
28120 }
28121 
28131 void QCPErrorBars::addData(double error)
28132 {
28133  mDataContainer->append(QCPErrorBarsData(error));
28134 }
28135 
28146 void QCPErrorBars::addData(double errorMinus, double errorPlus)
28147 {
28148  mDataContainer->append(QCPErrorBarsData(errorMinus, errorPlus));
28149 }
28150 
28151 /* inherits documentation from base class */
28153 {
28154  return mDataContainer->size();
28155 }
28156 
28157 /* inherits documentation from base class */
28158 double QCPErrorBars::dataMainKey(int index) const
28159 {
28160  if (mDataPlottable)
28161  return mDataPlottable->interface1D()->dataMainKey(index);
28162  else
28163  qDebug() << Q_FUNC_INFO << "no data plottable set";
28164  return 0;
28165 }
28166 
28167 /* inherits documentation from base class */
28168 double QCPErrorBars::dataSortKey(int index) const
28169 {
28170  if (mDataPlottable)
28171  return mDataPlottable->interface1D()->dataSortKey(index);
28172  else
28173  qDebug() << Q_FUNC_INFO << "no data plottable set";
28174  return 0;
28175 }
28176 
28177 /* inherits documentation from base class */
28178 double QCPErrorBars::dataMainValue(int index) const
28179 {
28180  if (mDataPlottable)
28181  return mDataPlottable->interface1D()->dataMainValue(index);
28182  else
28183  qDebug() << Q_FUNC_INFO << "no data plottable set";
28184  return 0;
28185 }
28186 
28187 /* inherits documentation from base class */
28189 {
28190  if (mDataPlottable)
28191  {
28192  const double value = mDataPlottable->interface1D()->dataMainValue(index);
28193  if (index >= 0 && index < mDataContainer->size() && mErrorType == etValueError)
28194  return {value-mDataContainer->at(index).errorMinus, value+mDataContainer->at(index).errorPlus};
28195  else
28196  return {value, value};
28197  } else
28198  {
28199  qDebug() << Q_FUNC_INFO << "no data plottable set";
28200  return {};
28201  }
28202 }
28203 
28204 /* inherits documentation from base class */
28205 QPointF QCPErrorBars::dataPixelPosition(int index) const
28206 {
28207  if (mDataPlottable)
28208  return mDataPlottable->interface1D()->dataPixelPosition(index);
28209  else
28210  qDebug() << Q_FUNC_INFO << "no data plottable set";
28211  return {};
28212 }
28213 
28214 /* inherits documentation from base class */
28216 {
28217  if (mDataPlottable)
28218  {
28219  return mDataPlottable->interface1D()->sortKeyIsMainKey();
28220  } else
28221  {
28222  qDebug() << Q_FUNC_INFO << "no data plottable set";
28223  return true;
28224  }
28225 }
28226 
28230 QCPDataSelection QCPErrorBars::selectTestRect(const QRectF &rect, bool onlySelectable) const
28231 {
28232  QCPDataSelection result;
28233  if (!mDataPlottable)
28234  return result;
28235  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
28236  return result;
28237  if (!mKeyAxis || !mValueAxis)
28238  return result;
28239 
28240  QCPErrorBarsDataContainer::const_iterator visibleBegin, visibleEnd;
28241  getVisibleDataBounds(visibleBegin, visibleEnd, QCPDataRange(0, dataCount()));
28242 
28243  QVector<QLineF> backbones, whiskers;
28244  for (QCPErrorBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
28245  {
28246  backbones.clear();
28247  whiskers.clear();
28248  getErrorBarLines(it, backbones, whiskers);
28249  foreach (const QLineF &backbone, backbones)
28250  {
28251  if (rectIntersectsLine(rect, backbone))
28252  {
28253  result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false);
28254  break;
28255  }
28256  }
28257  }
28258  result.simplify();
28259  return result;
28260 }
28261 
28262 /* inherits documentation from base class */
28263 int QCPErrorBars::findBegin(double sortKey, bool expandedRange) const
28264 {
28265  if (mDataPlottable)
28266  {
28267  if (mDataContainer->isEmpty())
28268  return 0;
28269  int beginIndex = mDataPlottable->interface1D()->findBegin(sortKey, expandedRange);
28270  if (beginIndex >= mDataContainer->size())
28271  beginIndex = mDataContainer->size()-1;
28272  return beginIndex;
28273  } else
28274  qDebug() << Q_FUNC_INFO << "no data plottable set";
28275  return 0;
28276 }
28277 
28278 /* inherits documentation from base class */
28279 int QCPErrorBars::findEnd(double sortKey, bool expandedRange) const
28280 {
28281  if (mDataPlottable)
28282  {
28283  if (mDataContainer->isEmpty())
28284  return 0;
28285  int endIndex = mDataPlottable->interface1D()->findEnd(sortKey, expandedRange);
28286  if (endIndex > mDataContainer->size())
28287  endIndex = mDataContainer->size();
28288  return endIndex;
28289  } else
28290  qDebug() << Q_FUNC_INFO << "no data plottable set";
28291  return 0;
28292 }
28293 
28302 double QCPErrorBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
28303 {
28304  if (!mDataPlottable) return -1;
28305 
28306  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
28307  return -1;
28308  if (!mKeyAxis || !mValueAxis)
28309  return -1;
28310 
28311  if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect))
28312  {
28313  QCPErrorBarsDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd();
28314  double result = pointDistance(pos, closestDataPoint);
28315  if (details)
28316  {
28317  int pointIndex = int(closestDataPoint-mDataContainer->constBegin());
28318  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
28319  }
28320  return result;
28321  } else
28322  return -1;
28323 }
28324 
28325 /* inherits documentation from base class */
28327 {
28328  if (!mDataPlottable) return;
28329  if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
28330  if (mKeyAxis.data()->range().size() <= 0 || mDataContainer->isEmpty()) return;
28331 
28332  // if the sort key isn't the main key, we must check the visibility for each data point/error bar individually
28333  // (getVisibleDataBounds applies range restriction, but otherwise can only return full data range):
28334  bool checkPointVisibility = !mDataPlottable->interface1D()->sortKeyIsMainKey();
28335 
28336  // check data validity if flag set:
28337 #ifdef QCUSTOMPLOT_CHECK_DATA
28338  QCPErrorBarsDataContainer::const_iterator it;
28339  for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it)
28340  {
28341  if (QCP::isInvalidData(it->errorMinus, it->errorPlus))
28342  qDebug() << Q_FUNC_INFO << "Data point at index" << it-mDataContainer->constBegin() << "invalid." << "Plottable name:" << name();
28343  }
28344 #endif
28345 
28347  painter->setBrush(Qt::NoBrush);
28348  // loop over and draw segments of unselected/selected data:
28349  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
28350  getDataSegments(selectedSegments, unselectedSegments);
28351  allSegments << unselectedSegments << selectedSegments;
28352  QVector<QLineF> backbones, whiskers;
28353  for (int i=0; i<allSegments.size(); ++i)
28354  {
28355  QCPErrorBarsDataContainer::const_iterator begin, end;
28356  getVisibleDataBounds(begin, end, allSegments.at(i));
28357  if (begin == end)
28358  continue;
28359 
28360  bool isSelectedSegment = i >= unselectedSegments.size();
28361  if (isSelectedSegment && mSelectionDecorator)
28362  mSelectionDecorator->applyPen(painter);
28363  else
28364  painter->setPen(mPen);
28365  if (painter->pen().capStyle() == Qt::SquareCap)
28366  {
28367  QPen capFixPen(painter->pen());
28368  capFixPen.setCapStyle(Qt::FlatCap);
28369  painter->setPen(capFixPen);
28370  }
28371  backbones.clear();
28372  whiskers.clear();
28373  for (QCPErrorBarsDataContainer::const_iterator it=begin; it!=end; ++it)
28374  {
28375  if (!checkPointVisibility || errorBarVisible(int(it-mDataContainer->constBegin())))
28376  getErrorBarLines(it, backbones, whiskers);
28377  }
28378  painter->drawLines(backbones);
28379  painter->drawLines(whiskers);
28380  }
28381 
28382  // draw other selection decoration that isn't just line/scatter pens and brushes:
28383  if (mSelectionDecorator)
28385 }
28386 
28387 /* inherits documentation from base class */
28388 void QCPErrorBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
28389 {
28391  painter->setPen(mPen);
28392  if (mErrorType == etValueError && mValueAxis && mValueAxis->orientation() == Qt::Vertical)
28393  {
28394  painter->drawLine(QLineF(rect.center().x(), rect.top()+2, rect.center().x(), rect.bottom()-1));
28395  painter->drawLine(QLineF(rect.center().x()-4, rect.top()+2, rect.center().x()+4, rect.top()+2));
28396  painter->drawLine(QLineF(rect.center().x()-4, rect.bottom()-1, rect.center().x()+4, rect.bottom()-1));
28397  } else
28398  {
28399  painter->drawLine(QLineF(rect.left()+2, rect.center().y(), rect.right()-2, rect.center().y()));
28400  painter->drawLine(QLineF(rect.left()+2, rect.center().y()-4, rect.left()+2, rect.center().y()+4));
28401  painter->drawLine(QLineF(rect.right()-2, rect.center().y()-4, rect.right()-2, rect.center().y()+4));
28402  }
28403 }
28404 
28405 /* inherits documentation from base class */
28406 QCPRange QCPErrorBars::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
28407 {
28408  if (!mDataPlottable)
28409  {
28410  foundRange = false;
28411  return {};
28412  }
28413 
28414  QCPRange range;
28415  bool haveLower = false;
28416  bool haveUpper = false;
28417  QCPErrorBarsDataContainer::const_iterator it;
28418  for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it)
28419  {
28420  if (mErrorType == etValueError)
28421  {
28422  // error bar doesn't extend in key dimension (except whisker but we ignore that here), so only use data point center
28423  const double current = mDataPlottable->interface1D()->dataMainKey(int(it-mDataContainer->constBegin()));
28424  if (qIsNaN(current)) continue;
28425  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
28426  {
28427  if (current < range.lower || !haveLower)
28428  {
28429  range.lower = current;
28430  haveLower = true;
28431  }
28432  if (current > range.upper || !haveUpper)
28433  {
28434  range.upper = current;
28435  haveUpper = true;
28436  }
28437  }
28438  } else // mErrorType == etKeyError
28439  {
28440  const double dataKey = mDataPlottable->interface1D()->dataMainKey(int(it-mDataContainer->constBegin()));
28441  if (qIsNaN(dataKey)) continue;
28442  // plus error:
28443  double current = dataKey + (qIsNaN(it->errorPlus) ? 0 : it->errorPlus);
28444  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
28445  {
28446  if (current > range.upper || !haveUpper)
28447  {
28448  range.upper = current;
28449  haveUpper = true;
28450  }
28451  }
28452  // minus error:
28453  current = dataKey - (qIsNaN(it->errorMinus) ? 0 : it->errorMinus);
28454  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
28455  {
28456  if (current < range.lower || !haveLower)
28457  {
28458  range.lower = current;
28459  haveLower = true;
28460  }
28461  }
28462  }
28463  }
28464 
28465  if (haveUpper && !haveLower)
28466  {
28467  range.lower = range.upper;
28468  haveLower = true;
28469  } else if (haveLower && !haveUpper)
28470  {
28471  range.upper = range.lower;
28472  haveUpper = true;
28473  }
28474 
28475  foundRange = haveLower && haveUpper;
28476  return range;
28477 }
28478 
28479 /* inherits documentation from base class */
28480 QCPRange QCPErrorBars::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
28481 {
28482  if (!mDataPlottable)
28483  {
28484  foundRange = false;
28485  return {};
28486  }
28487 
28488  QCPRange range;
28489  const bool restrictKeyRange = inKeyRange != QCPRange();
28490  bool haveLower = false;
28491  bool haveUpper = false;
28492  QCPErrorBarsDataContainer::const_iterator itBegin = mDataContainer->constBegin();
28493  QCPErrorBarsDataContainer::const_iterator itEnd = mDataContainer->constEnd();
28494  if (mDataPlottable->interface1D()->sortKeyIsMainKey() && restrictKeyRange)
28495  {
28496  itBegin = mDataContainer->constBegin()+findBegin(inKeyRange.lower, false);
28497  itEnd = mDataContainer->constBegin()+findEnd(inKeyRange.upper, false);
28498  }
28499  for (QCPErrorBarsDataContainer::const_iterator it = itBegin; it != itEnd; ++it)
28500  {
28501  if (restrictKeyRange)
28502  {
28503  const double dataKey = mDataPlottable->interface1D()->dataMainKey(int(it-mDataContainer->constBegin()));
28504  if (dataKey < inKeyRange.lower || dataKey > inKeyRange.upper)
28505  continue;
28506  }
28507  if (mErrorType == etValueError)
28508  {
28509  const double dataValue = mDataPlottable->interface1D()->dataMainValue(int(it-mDataContainer->constBegin()));
28510  if (qIsNaN(dataValue)) continue;
28511  // plus error:
28512  double current = dataValue + (qIsNaN(it->errorPlus) ? 0 : it->errorPlus);
28513  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
28514  {
28515  if (current > range.upper || !haveUpper)
28516  {
28517  range.upper = current;
28518  haveUpper = true;
28519  }
28520  }
28521  // minus error:
28522  current = dataValue - (qIsNaN(it->errorMinus) ? 0 : it->errorMinus);
28523  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
28524  {
28525  if (current < range.lower || !haveLower)
28526  {
28527  range.lower = current;
28528  haveLower = true;
28529  }
28530  }
28531  } else // mErrorType == etKeyError
28532  {
28533  // error bar doesn't extend in value dimension (except whisker but we ignore that here), so only use data point center
28534  const double current = mDataPlottable->interface1D()->dataMainValue(int(it-mDataContainer->constBegin()));
28535  if (qIsNaN(current)) continue;
28536  if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0))
28537  {
28538  if (current < range.lower || !haveLower)
28539  {
28540  range.lower = current;
28541  haveLower = true;
28542  }
28543  if (current > range.upper || !haveUpper)
28544  {
28545  range.upper = current;
28546  haveUpper = true;
28547  }
28548  }
28549  }
28550  }
28551 
28552  if (haveUpper && !haveLower)
28553  {
28554  range.lower = range.upper;
28555  haveLower = true;
28556  } else if (haveLower && !haveUpper)
28557  {
28558  range.upper = range.lower;
28559  haveUpper = true;
28560  }
28561 
28562  foundRange = haveLower && haveUpper;
28563  return range;
28564 }
28565 
28577 void QCPErrorBars::getErrorBarLines(QCPErrorBarsDataContainer::const_iterator it, QVector<QLineF> &backbones, QVector<QLineF> &whiskers) const
28578 {
28579  if (!mDataPlottable) return;
28580 
28581  int index = int(it-mDataContainer->constBegin());
28582  QPointF centerPixel = mDataPlottable->interface1D()->dataPixelPosition(index);
28583  if (qIsNaN(centerPixel.x()) || qIsNaN(centerPixel.y()))
28584  return;
28585  QCPAxis *errorAxis = mErrorType == etValueError ? mValueAxis.data() : mKeyAxis.data();
28586  QCPAxis *orthoAxis = mErrorType == etValueError ? mKeyAxis.data() : mValueAxis.data();
28587  const double centerErrorAxisPixel = errorAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y();
28588  const double centerOrthoAxisPixel = orthoAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y();
28589  const double centerErrorAxisCoord = errorAxis->pixelToCoord(centerErrorAxisPixel); // depending on plottable, this might be different from just mDataPlottable->interface1D()->dataMainKey/Value
28590  const double symbolGap = mSymbolGap*0.5*errorAxis->pixelOrientation();
28591  // plus error:
28592  double errorStart, errorEnd;
28593  if (!qIsNaN(it->errorPlus))
28594  {
28595  errorStart = centerErrorAxisPixel+symbolGap;
28596  errorEnd = errorAxis->coordToPixel(centerErrorAxisCoord+it->errorPlus);
28597  if (errorAxis->orientation() == Qt::Vertical)
28598  {
28599  if ((errorStart > errorEnd) != errorAxis->rangeReversed())
28600  backbones.append(QLineF(centerOrthoAxisPixel, errorStart, centerOrthoAxisPixel, errorEnd));
28601  whiskers.append(QLineF(centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5, errorEnd));
28602  } else
28603  {
28604  if ((errorStart < errorEnd) != errorAxis->rangeReversed())
28605  backbones.append(QLineF(errorStart, centerOrthoAxisPixel, errorEnd, centerOrthoAxisPixel));
28606  whiskers.append(QLineF(errorEnd, centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5));
28607  }
28608  }
28609  // minus error:
28610  if (!qIsNaN(it->errorMinus))
28611  {
28612  errorStart = centerErrorAxisPixel-symbolGap;
28613  errorEnd = errorAxis->coordToPixel(centerErrorAxisCoord-it->errorMinus);
28614  if (errorAxis->orientation() == Qt::Vertical)
28615  {
28616  if ((errorStart < errorEnd) != errorAxis->rangeReversed())
28617  backbones.append(QLineF(centerOrthoAxisPixel, errorStart, centerOrthoAxisPixel, errorEnd));
28618  whiskers.append(QLineF(centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5, errorEnd));
28619  } else
28620  {
28621  if ((errorStart > errorEnd) != errorAxis->rangeReversed())
28622  backbones.append(QLineF(errorStart, centerOrthoAxisPixel, errorEnd, centerOrthoAxisPixel));
28623  whiskers.append(QLineF(errorEnd, centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5));
28624  }
28625  }
28626 }
28627 
28646 void QCPErrorBars::getVisibleDataBounds(QCPErrorBarsDataContainer::const_iterator &begin, QCPErrorBarsDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const
28647 {
28648  QCPAxis *keyAxis = mKeyAxis.data();
28649  QCPAxis *valueAxis = mValueAxis.data();
28650  if (!keyAxis || !valueAxis)
28651  {
28652  qDebug() << Q_FUNC_INFO << "invalid key or value axis";
28653  end = mDataContainer->constEnd();
28654  begin = end;
28655  return;
28656  }
28657  if (!mDataPlottable || rangeRestriction.isEmpty())
28658  {
28659  end = mDataContainer->constEnd();
28660  begin = end;
28661  return;
28662  }
28663  if (!mDataPlottable->interface1D()->sortKeyIsMainKey())
28664  {
28665  // if the sort key isn't the main key, it's not possible to find a contiguous range of visible
28666  // data points, so this method then only applies the range restriction and otherwise returns
28667  // the full data range. Visibility checks must be done on a per-datapoin-basis during drawing
28668  QCPDataRange dataRange(0, mDataContainer->size());
28669  dataRange = dataRange.bounded(rangeRestriction);
28670  begin = mDataContainer->constBegin()+dataRange.begin();
28671  end = mDataContainer->constBegin()+dataRange.end();
28672  return;
28673  }
28674 
28675  // get visible data range via interface from data plottable, and then restrict to available error data points:
28676  const int n = qMin(mDataContainer->size(), mDataPlottable->interface1D()->dataCount());
28677  int beginIndex = mDataPlottable->interface1D()->findBegin(keyAxis->range().lower);
28678  int endIndex = mDataPlottable->interface1D()->findEnd(keyAxis->range().upper);
28679  int i = beginIndex;
28680  while (i > 0 && i < n && i > rangeRestriction.begin())
28681  {
28682  if (errorBarVisible(i))
28683  beginIndex = i;
28684  --i;
28685  }
28686  i = endIndex;
28687  while (i >= 0 && i < n && i < rangeRestriction.end())
28688  {
28689  if (errorBarVisible(i))
28690  endIndex = i+1;
28691  ++i;
28692  }
28693  QCPDataRange dataRange(beginIndex, endIndex);
28694  dataRange = dataRange.bounded(rangeRestriction.bounded(QCPDataRange(0, mDataContainer->size())));
28695  begin = mDataContainer->constBegin()+dataRange.begin();
28696  end = mDataContainer->constBegin()+dataRange.end();
28697 }
28698 
28705 double QCPErrorBars::pointDistance(const QPointF &pixelPoint, QCPErrorBarsDataContainer::const_iterator &closestData) const
28706 {
28707  closestData = mDataContainer->constEnd();
28708  if (!mDataPlottable || mDataContainer->isEmpty())
28709  return -1.0;
28710  if (!mKeyAxis || !mValueAxis)
28711  {
28712  qDebug() << Q_FUNC_INFO << "invalid key or value axis";
28713  return -1.0;
28714  }
28715 
28716  QCPErrorBarsDataContainer::const_iterator begin, end;
28717  getVisibleDataBounds(begin, end, QCPDataRange(0, dataCount()));
28718 
28719  // calculate minimum distances to error backbones (whiskers are ignored for speed) and find closestData iterator:
28720  double minDistSqr = (std::numeric_limits<double>::max)();
28721  QVector<QLineF> backbones, whiskers;
28722  for (QCPErrorBarsDataContainer::const_iterator it=begin; it!=end; ++it)
28723  {
28724  getErrorBarLines(it, backbones, whiskers);
28725  foreach (const QLineF &backbone, backbones)
28726  {
28727  const double currentDistSqr = QCPVector2D(pixelPoint).distanceSquaredToLine(backbone);
28728  if (currentDistSqr < minDistSqr)
28729  {
28730  minDistSqr = currentDistSqr;
28731  closestData = it;
28732  }
28733  }
28734  }
28735  return qSqrt(minDistSqr);
28736 }
28737 
28745 void QCPErrorBars::getDataSegments(QList<QCPDataRange> &selectedSegments, QList<QCPDataRange> &unselectedSegments) const
28746 {
28747  selectedSegments.clear();
28748  unselectedSegments.clear();
28749  if (mSelectable == QCP::stWhole) // stWhole selection type draws the entire plottable with selected style if mSelection isn't empty
28750  {
28751  if (selected())
28752  selectedSegments << QCPDataRange(0, dataCount());
28753  else
28754  unselectedSegments << QCPDataRange(0, dataCount());
28755  } else
28756  {
28757  QCPDataSelection sel(selection());
28758  sel.simplify();
28759  selectedSegments = sel.dataRanges();
28760  unselectedSegments = sel.inverse(QCPDataRange(0, dataCount())).dataRanges();
28761  }
28762 }
28763 
28773 bool QCPErrorBars::errorBarVisible(int index) const
28774 {
28775  QPointF centerPixel = mDataPlottable->interface1D()->dataPixelPosition(index);
28776  const double centerKeyPixel = mKeyAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y();
28777  if (qIsNaN(centerKeyPixel))
28778  return false;
28779 
28780  double keyMin, keyMax;
28781  if (mErrorType == etKeyError)
28782  {
28783  const double centerKey = mKeyAxis->pixelToCoord(centerKeyPixel);
28784  const double errorPlus = mDataContainer->at(index).errorPlus;
28785  const double errorMinus = mDataContainer->at(index).errorMinus;
28786  keyMax = centerKey+(qIsNaN(errorPlus) ? 0 : errorPlus);
28787  keyMin = centerKey-(qIsNaN(errorMinus) ? 0 : errorMinus);
28788  } else // mErrorType == etValueError
28789  {
28790  keyMax = mKeyAxis->pixelToCoord(centerKeyPixel+mWhiskerWidth*0.5*mKeyAxis->pixelOrientation());
28791  keyMin = mKeyAxis->pixelToCoord(centerKeyPixel-mWhiskerWidth*0.5*mKeyAxis->pixelOrientation());
28792  }
28793  return ((keyMax > mKeyAxis->range().lower) && (keyMin < mKeyAxis->range().upper));
28794 }
28795 
28803 bool QCPErrorBars::rectIntersectsLine(const QRectF &pixelRect, const QLineF &line) const
28804 {
28805  if (pixelRect.left() > line.x1() && pixelRect.left() > line.x2())
28806  return false;
28807  else if (pixelRect.right() < line.x1() && pixelRect.right() < line.x2())
28808  return false;
28809  else if (pixelRect.top() > line.y1() && pixelRect.top() > line.y2())
28810  return false;
28811  else if (pixelRect.bottom() < line.y1() && pixelRect.bottom() < line.y2())
28812  return false;
28813  else
28814  return true;
28815 }
28816 /* end of 'src/plottables/plottable-errorbar.cpp' */
28817 
28818 
28819 /* including file 'src/items/item-straightline.cpp' */
28820 /* modified 2021-03-29T02:30:44, size 7596 */
28821 
28825 
28841  QCPAbstractItem(parentPlot),
28842  point1(createPosition(QLatin1String("point1"))),
28843  point2(createPosition(QLatin1String("point2")))
28844 {
28845  point1->setCoords(0, 0);
28846  point2->setCoords(1, 1);
28847 
28848  setPen(QPen(Qt::black));
28849  setSelectedPen(QPen(Qt::blue,2));
28850 }
28851 
28853 {
28854 }
28855 
28861 void QCPItemStraightLine::setPen(const QPen &pen)
28862 {
28863  mPen = pen;
28864 }
28865 
28872 {
28873  mSelectedPen = pen;
28874 }
28875 
28876 /* inherits documentation from base class */
28877 double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
28878 {
28879  Q_UNUSED(details)
28880  if (onlySelectable && !mSelectable)
28881  return -1;
28882 
28884 }
28885 
28886 /* inherits documentation from base class */
28888 {
28889  QCPVector2D start(point1->pixelPosition());
28891  // get visible segment of straight line inside clipRect:
28892  int clipPad = qCeil(mainPen().widthF());
28893  QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
28894  // paint visible segment, if existent:
28895  if (!line.isNull())
28896  {
28897  painter->setPen(mainPen());
28898  painter->drawLine(line);
28899  }
28900 }
28901 
28909 QLineF QCPItemStraightLine::getRectClippedStraightLine(const QCPVector2D &base, const QCPVector2D &vec, const QRect &rect) const
28910 {
28911  double bx, by;
28912  double gamma;
28913  QLineF result;
28914  if (vec.x() == 0 && vec.y() == 0)
28915  return result;
28916  if (qFuzzyIsNull(vec.x())) // line is vertical
28917  {
28918  // check top of rect:
28919  bx = rect.left();
28920  by = rect.top();
28921  gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
28922  if (gamma >= 0 && gamma <= rect.width())
28923  result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical
28924  } else if (qFuzzyIsNull(vec.y())) // line is horizontal
28925  {
28926  // check left of rect:
28927  bx = rect.left();
28928  by = rect.top();
28929  gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
28930  if (gamma >= 0 && gamma <= rect.height())
28931  result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal
28932  } else // line is skewed
28933  {
28934  QList<QCPVector2D> pointVectors;
28935  // check top of rect:
28936  bx = rect.left();
28937  by = rect.top();
28938  gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
28939  if (gamma >= 0 && gamma <= rect.width())
28940  pointVectors.append(QCPVector2D(bx+gamma, by));
28941  // check bottom of rect:
28942  bx = rect.left();
28943  by = rect.bottom();
28944  gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
28945  if (gamma >= 0 && gamma <= rect.width())
28946  pointVectors.append(QCPVector2D(bx+gamma, by));
28947  // check left of rect:
28948  bx = rect.left();
28949  by = rect.top();
28950  gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
28951  if (gamma >= 0 && gamma <= rect.height())
28952  pointVectors.append(QCPVector2D(bx, by+gamma));
28953  // check right of rect:
28954  bx = rect.right();
28955  by = rect.top();
28956  gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
28957  if (gamma >= 0 && gamma <= rect.height())
28958  pointVectors.append(QCPVector2D(bx, by+gamma));
28959 
28960  // evaluate points:
28961  if (pointVectors.size() == 2)
28962  {
28963  result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
28964  } else if (pointVectors.size() > 2)
28965  {
28966  // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
28967  double distSqrMax = 0;
28968  QCPVector2D pv1, pv2;
28969  for (int i=0; i<pointVectors.size()-1; ++i)
28970  {
28971  for (int k=i+1; k<pointVectors.size(); ++k)
28972  {
28973  double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
28974  if (distSqr > distSqrMax)
28975  {
28976  pv1 = pointVectors.at(i);
28977  pv2 = pointVectors.at(k);
28978  distSqrMax = distSqr;
28979  }
28980  }
28981  }
28982  result.setPoints(pv1.toPointF(), pv2.toPointF());
28983  }
28984  }
28985  return result;
28986 }
28987 
28994 {
28995  return mSelected ? mSelectedPen : mPen;
28996 }
28997 /* end of 'src/items/item-straightline.cpp' */
28998 
28999 
29000 /* including file 'src/items/item-line.cpp' */
29001 /* modified 2021-03-29T02:30:44, size 8525 */
29002 
29006 
29024  QCPAbstractItem(parentPlot),
29025  start(createPosition(QLatin1String("start"))),
29026  end(createPosition(QLatin1String("end")))
29027 {
29028  start->setCoords(0, 0);
29029  end->setCoords(1, 1);
29030 
29031  setPen(QPen(Qt::black));
29032  setSelectedPen(QPen(Qt::blue,2));
29033 }
29034 
29036 {
29037 }
29038 
29044 void QCPItemLine::setPen(const QPen &pen)
29045 {
29046  mPen = pen;
29047 }
29048 
29054 void QCPItemLine::setSelectedPen(const QPen &pen)
29055 {
29056  mSelectedPen = pen;
29057 }
29058 
29068 {
29069  mHead = head;
29070 }
29071 
29081 {
29082  mTail = tail;
29083 }
29084 
29085 /* inherits documentation from base class */
29086 double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
29087 {
29088  Q_UNUSED(details)
29089  if (onlySelectable && !mSelectable)
29090  return -1;
29091 
29092  return qSqrt(QCPVector2D(pos).distanceSquaredToLine(start->pixelPosition(), end->pixelPosition()));
29093 }
29094 
29095 /* inherits documentation from base class */
29097 {
29098  QCPVector2D startVec(start->pixelPosition());
29099  QCPVector2D endVec(end->pixelPosition());
29100  if (qFuzzyIsNull((startVec-endVec).lengthSquared()))
29101  return;
29102  // get visible segment of straight line inside clipRect:
29103  int clipPad = int(qMax(mHead.boundingDistance(), mTail.boundingDistance()));
29104  clipPad = qMax(clipPad, qCeil(mainPen().widthF()));
29105  QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
29106  // paint visible segment, if existent:
29107  if (!line.isNull())
29108  {
29109  painter->setPen(mainPen());
29110  painter->drawLine(line);
29111  painter->setBrush(Qt::SolidPattern);
29113  mTail.draw(painter, startVec, startVec-endVec);
29115  mHead.draw(painter, endVec, endVec-startVec);
29116  }
29117 }
29118 
29126 QLineF QCPItemLine::getRectClippedLine(const QCPVector2D &start, const QCPVector2D &end, const QRect &rect) const
29127 {
29128  bool containsStart = rect.contains(qRound(start.x()), qRound(start.y()));
29129  bool containsEnd = rect.contains(qRound(end.x()), qRound(end.y()));
29130  if (containsStart && containsEnd)
29131  return {start.toPointF(), end.toPointF()};
29132 
29133  QCPVector2D base = start;
29134  QCPVector2D vec = end-start;
29135  double bx, by;
29136  double gamma, mu;
29137  QLineF result;
29138  QList<QCPVector2D> pointVectors;
29139 
29140  if (!qFuzzyIsNull(vec.y())) // line is not horizontal
29141  {
29142  // check top of rect:
29143  bx = rect.left();
29144  by = rect.top();
29145  mu = (by-base.y())/vec.y();
29146  if (mu >= 0 && mu <= 1)
29147  {
29148  gamma = base.x()-bx + mu*vec.x();
29149  if (gamma >= 0 && gamma <= rect.width())
29150  pointVectors.append(QCPVector2D(bx+gamma, by));
29151  }
29152  // check bottom of rect:
29153  bx = rect.left();
29154  by = rect.bottom();
29155  mu = (by-base.y())/vec.y();
29156  if (mu >= 0 && mu <= 1)
29157  {
29158  gamma = base.x()-bx + mu*vec.x();
29159  if (gamma >= 0 && gamma <= rect.width())
29160  pointVectors.append(QCPVector2D(bx+gamma, by));
29161  }
29162  }
29163  if (!qFuzzyIsNull(vec.x())) // line is not vertical
29164  {
29165  // check left of rect:
29166  bx = rect.left();
29167  by = rect.top();
29168  mu = (bx-base.x())/vec.x();
29169  if (mu >= 0 && mu <= 1)
29170  {
29171  gamma = base.y()-by + mu*vec.y();
29172  if (gamma >= 0 && gamma <= rect.height())
29173  pointVectors.append(QCPVector2D(bx, by+gamma));
29174  }
29175  // check right of rect:
29176  bx = rect.right();
29177  by = rect.top();
29178  mu = (bx-base.x())/vec.x();
29179  if (mu >= 0 && mu <= 1)
29180  {
29181  gamma = base.y()-by + mu*vec.y();
29182  if (gamma >= 0 && gamma <= rect.height())
29183  pointVectors.append(QCPVector2D(bx, by+gamma));
29184  }
29185  }
29186 
29187  if (containsStart)
29188  pointVectors.append(start);
29189  if (containsEnd)
29190  pointVectors.append(end);
29191 
29192  // evaluate points:
29193  if (pointVectors.size() == 2)
29194  {
29195  result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
29196  } else if (pointVectors.size() > 2)
29197  {
29198  // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance:
29199  double distSqrMax = 0;
29200  QCPVector2D pv1, pv2;
29201  for (int i=0; i<pointVectors.size()-1; ++i)
29202  {
29203  for (int k=i+1; k<pointVectors.size(); ++k)
29204  {
29205  double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
29206  if (distSqr > distSqrMax)
29207  {
29208  pv1 = pointVectors.at(i);
29209  pv2 = pointVectors.at(k);
29210  distSqrMax = distSqr;
29211  }
29212  }
29213  }
29214  result.setPoints(pv1.toPointF(), pv2.toPointF());
29215  }
29216  return result;
29217 }
29218 
29225 {
29226  return mSelected ? mSelectedPen : mPen;
29227 }
29228 /* end of 'src/items/item-line.cpp' */
29229 
29230 
29231 /* including file 'src/items/item-curve.cpp' */
29232 /* modified 2021-03-29T02:30:44, size 7273 */
29233 
29237 
29262  QCPAbstractItem(parentPlot),
29263  start(createPosition(QLatin1String("start"))),
29264  startDir(createPosition(QLatin1String("startDir"))),
29265  endDir(createPosition(QLatin1String("endDir"))),
29266  end(createPosition(QLatin1String("end")))
29267 {
29268  start->setCoords(0, 0);
29269  startDir->setCoords(0.5, 0);
29270  endDir->setCoords(0, 0.5);
29271  end->setCoords(1, 1);
29272 
29273  setPen(QPen(Qt::black));
29274  setSelectedPen(QPen(Qt::blue,2));
29275 }
29276 
29278 {
29279 }
29280 
29286 void QCPItemCurve::setPen(const QPen &pen)
29287 {
29288  mPen = pen;
29289 }
29290 
29296 void QCPItemCurve::setSelectedPen(const QPen &pen)
29297 {
29298  mSelectedPen = pen;
29299 }
29300 
29310 {
29311  mHead = head;
29312 }
29313 
29323 {
29324  mTail = tail;
29325 }
29326 
29327 /* inherits documentation from base class */
29328 double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
29329 {
29330  Q_UNUSED(details)
29331  if (onlySelectable && !mSelectable)
29332  return -1;
29333 
29334  QPointF startVec(start->pixelPosition());
29335  QPointF startDirVec(startDir->pixelPosition());
29336  QPointF endDirVec(endDir->pixelPosition());
29337  QPointF endVec(end->pixelPosition());
29338 
29339  QPainterPath cubicPath(startVec);
29340  cubicPath.cubicTo(startDirVec, endDirVec, endVec);
29341 
29342  QList<QPolygonF> polygons = cubicPath.toSubpathPolygons();
29343  if (polygons.isEmpty())
29344  return -1;
29345  const QPolygonF polygon = polygons.first();
29346  QCPVector2D p(pos);
29347  double minDistSqr = (std::numeric_limits<double>::max)();
29348  for (int i=1; i<polygon.size(); ++i)
29349  {
29350  double distSqr = p.distanceSquaredToLine(polygon.at(i-1), polygon.at(i));
29351  if (distSqr < minDistSqr)
29352  minDistSqr = distSqr;
29353  }
29354  return qSqrt(minDistSqr);
29355 }
29356 
29357 /* inherits documentation from base class */
29359 {
29360  QCPVector2D startVec(start->pixelPosition());
29361  QCPVector2D startDirVec(startDir->pixelPosition());
29362  QCPVector2D endDirVec(endDir->pixelPosition());
29363  QCPVector2D endVec(end->pixelPosition());
29364  if ((endVec-startVec).length() > 1e10) // too large curves cause crash
29365  return;
29366 
29367  QPainterPath cubicPath(startVec.toPointF());
29368  cubicPath.cubicTo(startDirVec.toPointF(), endDirVec.toPointF(), endVec.toPointF());
29369 
29370  // paint visible segment, if existent:
29371  const int clipEnlarge = qCeil(mainPen().widthF());
29372  QRect clip = clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge);
29373  QRect cubicRect = cubicPath.controlPointRect().toRect();
29374  if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position
29375  cubicRect.adjust(0, 0, 1, 1);
29376  if (clip.intersects(cubicRect))
29377  {
29378  painter->setPen(mainPen());
29379  painter->drawPath(cubicPath);
29380  painter->setBrush(Qt::SolidPattern);
29382  mTail.draw(painter, startVec, M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI);
29384  mHead.draw(painter, endVec, -cubicPath.angleAtPercent(1)/180.0*M_PI);
29385  }
29386 }
29387 
29394 {
29395  return mSelected ? mSelectedPen : mPen;
29396 }
29397 /* end of 'src/items/item-curve.cpp' */
29398 
29399 
29400 /* including file 'src/items/item-rect.cpp' */
29401 /* modified 2021-03-29T02:30:44, size 6472 */
29402 
29406 
29422  QCPAbstractItem(parentPlot),
29423  topLeft(createPosition(QLatin1String("topLeft"))),
29424  bottomRight(createPosition(QLatin1String("bottomRight"))),
29425  top(createAnchor(QLatin1String("top"), aiTop)),
29426  topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
29427  right(createAnchor(QLatin1String("right"), aiRight)),
29428  bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
29429  bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
29430  left(createAnchor(QLatin1String("left"), aiLeft))
29431 {
29432  topLeft->setCoords(0, 1);
29433  bottomRight->setCoords(1, 0);
29434 
29435  setPen(QPen(Qt::black));
29436  setSelectedPen(QPen(Qt::blue,2));
29437  setBrush(Qt::NoBrush);
29438  setSelectedBrush(Qt::NoBrush);
29439 }
29440 
29442 {
29443 }
29444 
29450 void QCPItemRect::setPen(const QPen &pen)
29451 {
29452  mPen = pen;
29453 }
29454 
29460 void QCPItemRect::setSelectedPen(const QPen &pen)
29461 {
29462  mSelectedPen = pen;
29463 }
29464 
29471 void QCPItemRect::setBrush(const QBrush &brush)
29472 {
29473  mBrush = brush;
29474 }
29475 
29482 void QCPItemRect::setSelectedBrush(const QBrush &brush)
29483 {
29485 }
29486 
29487 /* inherits documentation from base class */
29488 double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
29489 {
29490  Q_UNUSED(details)
29491  if (onlySelectable && !mSelectable)
29492  return -1;
29493 
29494  QRectF rect = QRectF(topLeft->pixelPosition(), bottomRight->pixelPosition()).normalized();
29495  bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
29496  return rectDistance(rect, pos, filledRect);
29497 }
29498 
29499 /* inherits documentation from base class */
29501 {
29502  QPointF p1 = topLeft->pixelPosition();
29503  QPointF p2 = bottomRight->pixelPosition();
29504  if (p1.toPoint() == p2.toPoint())
29505  return;
29506  QRectF rect = QRectF(p1, p2).normalized();
29507  double clipPad = mainPen().widthF();
29508  QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
29509  if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect
29510  {
29511  painter->setPen(mainPen());
29512  painter->setBrush(mainBrush());
29513  painter->drawRect(rect);
29514  }
29515 }
29516 
29517 /* inherits documentation from base class */
29518 QPointF QCPItemRect::anchorPixelPosition(int anchorId) const
29519 {
29520  QRectF rect = QRectF(topLeft->pixelPosition(), bottomRight->pixelPosition());
29521  switch (anchorId)
29522  {
29523  case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
29524  case aiTopRight: return rect.topRight();
29525  case aiRight: return (rect.topRight()+rect.bottomRight())*0.5;
29526  case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5;
29527  case aiBottomLeft: return rect.bottomLeft();
29528  case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
29529  }
29530 
29531  qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
29532  return {};
29533 }
29534 
29541 {
29542  return mSelected ? mSelectedPen : mPen;
29543 }
29544 
29551 {
29552  return mSelected ? mSelectedBrush : mBrush;
29553 }
29554 /* end of 'src/items/item-rect.cpp' */
29555 
29556 
29557 /* including file 'src/items/item-text.cpp' */
29558 /* modified 2021-03-29T02:30:44, size 13335 */
29559 
29563 
29585  QCPAbstractItem(parentPlot),
29586  position(createPosition(QLatin1String("position"))),
29587  topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)),
29588  top(createAnchor(QLatin1String("top"), aiTop)),
29589  topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
29590  right(createAnchor(QLatin1String("right"), aiRight)),
29591  bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)),
29592  bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
29593  bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
29594  left(createAnchor(QLatin1String("left"), aiLeft)),
29595  mText(QLatin1String("text")),
29596  mPositionAlignment(Qt::AlignCenter),
29597  mTextAlignment(Qt::AlignTop|Qt::AlignHCenter),
29598  mRotation(0)
29599 {
29600  position->setCoords(0, 0);
29601 
29602  setPen(Qt::NoPen);
29603  setSelectedPen(Qt::NoPen);
29604  setBrush(Qt::NoBrush);
29605  setSelectedBrush(Qt::NoBrush);
29606  setColor(Qt::black);
29607  setSelectedColor(Qt::blue);
29608 }
29609 
29611 {
29612 }
29613 
29617 void QCPItemText::setColor(const QColor &color)
29618 {
29619  mColor = color;
29620 }
29621 
29626 {
29628 }
29629 
29636 void QCPItemText::setPen(const QPen &pen)
29637 {
29638  mPen = pen;
29639 }
29640 
29647 void QCPItemText::setSelectedPen(const QPen &pen)
29648 {
29649  mSelectedPen = pen;
29650 }
29651 
29658 void QCPItemText::setBrush(const QBrush &brush)
29659 {
29660  mBrush = brush;
29661 }
29662 
29669 void QCPItemText::setSelectedBrush(const QBrush &brush)
29670 {
29672 }
29673 
29679 void QCPItemText::setFont(const QFont &font)
29680 {
29681  mFont = font;
29682 }
29683 
29689 void QCPItemText::setSelectedFont(const QFont &font)
29690 {
29691  mSelectedFont = font;
29692 }
29693 
29700 void QCPItemText::setText(const QString &text)
29701 {
29702  mText = text;
29703 }
29704 
29717 void QCPItemText::setPositionAlignment(Qt::Alignment alignment)
29718 {
29719  mPositionAlignment = alignment;
29720 }
29721 
29725 void QCPItemText::setTextAlignment(Qt::Alignment alignment)
29726 {
29727  mTextAlignment = alignment;
29728 }
29729 
29734 void QCPItemText::setRotation(double degrees)
29735 {
29736  mRotation = degrees;
29737 }
29738 
29743 void QCPItemText::setPadding(const QMargins &padding)
29744 {
29745  mPadding = padding;
29746 }
29747 
29748 /* inherits documentation from base class */
29749 double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
29750 {
29751  Q_UNUSED(details)
29752  if (onlySelectable && !mSelectable)
29753  return -1;
29754 
29755  // The rect may be rotated, so we transform the actual clicked pos to the rotated
29756  // coordinate system, so we can use the normal rectDistance function for non-rotated rects:
29757  QPointF positionPixels(position->pixelPosition());
29758  QTransform inputTransform;
29759  inputTransform.translate(positionPixels.x(), positionPixels.y());
29760  inputTransform.rotate(-mRotation);
29761  inputTransform.translate(-positionPixels.x(), -positionPixels.y());
29762  QPointF rotatedPos = inputTransform.map(pos);
29763  QFontMetrics fontMetrics(mFont);
29764  QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
29765  QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
29766  QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment);
29767  textBoxRect.moveTopLeft(textPos.toPoint());
29768 
29769  return rectDistance(textBoxRect, rotatedPos, true);
29770 }
29771 
29772 /* inherits documentation from base class */
29774 {
29775  QPointF pos(position->pixelPosition());
29776  QTransform transform = painter->transform();
29777  transform.translate(pos.x(), pos.y());
29778  if (!qFuzzyIsNull(mRotation))
29779  transform.rotate(mRotation);
29780  painter->setFont(mainFont());
29781  QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
29782  QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
29783  QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
29784  textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top()));
29785  textBoxRect.moveTopLeft(textPos.toPoint());
29786  int clipPad = qCeil(mainPen().widthF());
29787  QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
29788  if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect())))
29789  {
29790  painter->setTransform(transform);
29791  if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) ||
29792  (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0))
29793  {
29794  painter->setPen(mainPen());
29795  painter->setBrush(mainBrush());
29796  painter->drawRect(textBoxRect);
29797  }
29798  painter->setBrush(Qt::NoBrush);
29799  painter->setPen(QPen(mainColor()));
29800  painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText);
29801  }
29802 }
29803 
29804 /* inherits documentation from base class */
29805 QPointF QCPItemText::anchorPixelPosition(int anchorId) const
29806 {
29807  // get actual rect points (pretty much copied from draw function):
29808  QPointF pos(position->pixelPosition());
29809  QTransform transform;
29810  transform.translate(pos.x(), pos.y());
29811  if (!qFuzzyIsNull(mRotation))
29812  transform.rotate(mRotation);
29813  QFontMetrics fontMetrics(mainFont());
29814  QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText);
29815  QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom());
29816  QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation
29817  textBoxRect.moveTopLeft(textPos.toPoint());
29818  QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect));
29819 
29820  switch (anchorId)
29821  {
29822  case aiTopLeft: return rectPoly.at(0);
29823  case aiTop: return (rectPoly.at(0)+rectPoly.at(1))*0.5;
29824  case aiTopRight: return rectPoly.at(1);
29825  case aiRight: return (rectPoly.at(1)+rectPoly.at(2))*0.5;
29826  case aiBottomRight: return rectPoly.at(2);
29827  case aiBottom: return (rectPoly.at(2)+rectPoly.at(3))*0.5;
29828  case aiBottomLeft: return rectPoly.at(3);
29829  case aiLeft: return (rectPoly.at(3)+rectPoly.at(0))*0.5;
29830  }
29831 
29832  qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
29833  return {};
29834 }
29835 
29846 QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const
29847 {
29848  if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop))
29849  return pos;
29850 
29851  QPointF result = pos; // start at top left
29852  if (positionAlignment.testFlag(Qt::AlignHCenter))
29853  result.rx() -= rect.width()/2.0;
29854  else if (positionAlignment.testFlag(Qt::AlignRight))
29855  result.rx() -= rect.width();
29856  if (positionAlignment.testFlag(Qt::AlignVCenter))
29857  result.ry() -= rect.height()/2.0;
29858  else if (positionAlignment.testFlag(Qt::AlignBottom))
29859  result.ry() -= rect.height();
29860  return result;
29861 }
29862 
29869 {
29870  return mSelected ? mSelectedFont : mFont;
29871 }
29872 
29879 {
29880  return mSelected ? mSelectedColor : mColor;
29881 }
29882 
29889 {
29890  return mSelected ? mSelectedPen : mPen;
29891 }
29892 
29899 {
29900  return mSelected ? mSelectedBrush : mBrush;
29901 }
29902 /* end of 'src/items/item-text.cpp' */
29903 
29904 
29905 /* including file 'src/items/item-ellipse.cpp' */
29906 /* modified 2021-03-29T02:30:44, size 7881 */
29907 
29911 
29927  QCPAbstractItem(parentPlot),
29928  topLeft(createPosition(QLatin1String("topLeft"))),
29929  bottomRight(createPosition(QLatin1String("bottomRight"))),
29930  topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)),
29931  top(createAnchor(QLatin1String("top"), aiTop)),
29932  topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)),
29933  right(createAnchor(QLatin1String("right"), aiRight)),
29934  bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)),
29935  bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
29936  bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)),
29937  left(createAnchor(QLatin1String("left"), aiLeft)),
29938  center(createAnchor(QLatin1String("center"), aiCenter))
29939 {
29940  topLeft->setCoords(0, 1);
29941  bottomRight->setCoords(1, 0);
29942 
29943  setPen(QPen(Qt::black));
29944  setSelectedPen(QPen(Qt::blue, 2));
29945  setBrush(Qt::NoBrush);
29946  setSelectedBrush(Qt::NoBrush);
29947 }
29948 
29950 {
29951 }
29952 
29958 void QCPItemEllipse::setPen(const QPen &pen)
29959 {
29960  mPen = pen;
29961 }
29962 
29968 void QCPItemEllipse::setSelectedPen(const QPen &pen)
29969 {
29970  mSelectedPen = pen;
29971 }
29972 
29979 void QCPItemEllipse::setBrush(const QBrush &brush)
29980 {
29981  mBrush = brush;
29982 }
29983 
29990 void QCPItemEllipse::setSelectedBrush(const QBrush &brush)
29991 {
29993 }
29994 
29995 /* inherits documentation from base class */
29996 double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
29997 {
29998  Q_UNUSED(details)
29999  if (onlySelectable && !mSelectable)
30000  return -1;
30001 
30002  QPointF p1 = topLeft->pixelPosition();
30003  QPointF p2 = bottomRight->pixelPosition();
30004  QPointF center((p1+p2)/2.0);
30005  double a = qAbs(p1.x()-p2.x())/2.0;
30006  double b = qAbs(p1.y()-p2.y())/2.0;
30007  double x = pos.x()-center.x();
30008  double y = pos.y()-center.y();
30009 
30010  // distance to border:
30011  double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b));
30012  double result = qAbs(c-1)*qSqrt(x*x+y*y);
30013  // filled ellipse, allow click inside to count as hit:
30014  if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
30015  {
30016  if (x*x/(a*a) + y*y/(b*b) <= 1)
30017  result = mParentPlot->selectionTolerance()*0.99;
30018  }
30019  return result;
30020 }
30021 
30022 /* inherits documentation from base class */
30024 {
30025  QPointF p1 = topLeft->pixelPosition();
30026  QPointF p2 = bottomRight->pixelPosition();
30027  if (p1.toPoint() == p2.toPoint())
30028  return;
30029  QRectF ellipseRect = QRectF(p1, p2).normalized();
30030  const int clipEnlarge = qCeil(mainPen().widthF());
30031  QRect clip = clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge);
30032  if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect
30033  {
30034  painter->setPen(mainPen());
30035  painter->setBrush(mainBrush());
30036 #ifdef __EXCEPTIONS
30037  try // drawEllipse sometimes throws exceptions if ellipse is too big
30038  {
30039 #endif
30040  painter->drawEllipse(ellipseRect);
30041 #ifdef __EXCEPTIONS
30042  } catch (...)
30043  {
30044  qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible";
30045  setVisible(false);
30046  }
30047 #endif
30048  }
30049 }
30050 
30051 /* inherits documentation from base class */
30052 QPointF QCPItemEllipse::anchorPixelPosition(int anchorId) const
30053 {
30054  QRectF rect = QRectF(topLeft->pixelPosition(), bottomRight->pixelPosition());
30055  switch (anchorId)
30056  {
30057  case aiTopLeftRim: return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2);
30058  case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
30059  case aiTopRightRim: return rect.center()+(rect.topRight()-rect.center())*1/qSqrt(2);
30060  case aiRight: return (rect.topRight()+rect.bottomRight())*0.5;
30061  case aiBottomRightRim: return rect.center()+(rect.bottomRight()-rect.center())*1/qSqrt(2);
30062  case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5;
30063  case aiBottomLeftRim: return rect.center()+(rect.bottomLeft()-rect.center())*1/qSqrt(2);
30064  case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
30065  case aiCenter: return (rect.topLeft()+rect.bottomRight())*0.5;
30066  }
30067 
30068  qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
30069  return {};
30070 }
30071 
30078 {
30079  return mSelected ? mSelectedPen : mPen;
30080 }
30081 
30088 {
30089  return mSelected ? mSelectedBrush : mBrush;
30090 }
30091 /* end of 'src/items/item-ellipse.cpp' */
30092 
30093 
30094 /* including file 'src/items/item-pixmap.cpp' */
30095 /* modified 2021-03-29T02:30:44, size 10622 */
30096 
30100 
30122  QCPAbstractItem(parentPlot),
30123  topLeft(createPosition(QLatin1String("topLeft"))),
30124  bottomRight(createPosition(QLatin1String("bottomRight"))),
30125  top(createAnchor(QLatin1String("top"), aiTop)),
30126  topRight(createAnchor(QLatin1String("topRight"), aiTopRight)),
30127  right(createAnchor(QLatin1String("right"), aiRight)),
30128  bottom(createAnchor(QLatin1String("bottom"), aiBottom)),
30129  bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)),
30130  left(createAnchor(QLatin1String("left"), aiLeft)),
30131  mScaled(false),
30132  mScaledPixmapInvalidated(true),
30133  mAspectRatioMode(Qt::KeepAspectRatio),
30134  mTransformationMode(Qt::SmoothTransformation)
30135 {
30136  topLeft->setCoords(0, 1);
30137  bottomRight->setCoords(1, 0);
30138 
30139  setPen(Qt::NoPen);
30140  setSelectedPen(QPen(Qt::blue));
30141 }
30142 
30144 {
30145 }
30146 
30150 void QCPItemPixmap::setPixmap(const QPixmap &pixmap)
30151 {
30152  mPixmap = pixmap;
30153  mScaledPixmapInvalidated = true;
30154  if (mPixmap.isNull())
30155  qDebug() << Q_FUNC_INFO << "pixmap is null";
30156 }
30157 
30162 void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode)
30163 {
30164  mScaled = scaled;
30167  mScaledPixmapInvalidated = true;
30168 }
30169 
30175 void QCPItemPixmap::setPen(const QPen &pen)
30176 {
30177  mPen = pen;
30178 }
30179 
30185 void QCPItemPixmap::setSelectedPen(const QPen &pen)
30186 {
30187  mSelectedPen = pen;
30188 }
30189 
30190 /* inherits documentation from base class */
30191 double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
30192 {
30193  Q_UNUSED(details)
30194  if (onlySelectable && !mSelectable)
30195  return -1;
30196 
30197  return rectDistance(getFinalRect(), pos, true);
30198 }
30199 
30200 /* inherits documentation from base class */
30202 {
30203  bool flipHorz = false;
30204  bool flipVert = false;
30205  QRect rect = getFinalRect(&flipHorz, &flipVert);
30206  int clipPad = mainPen().style() == Qt::NoPen ? 0 : qCeil(mainPen().widthF());
30207  QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
30208  if (boundingRect.intersects(clipRect()))
30209  {
30210  updateScaledPixmap(rect, flipHorz, flipVert);
30211  painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap);
30212  QPen pen = mainPen();
30213  if (pen.style() != Qt::NoPen)
30214  {
30215  painter->setPen(pen);
30216  painter->setBrush(Qt::NoBrush);
30217  painter->drawRect(rect);
30218  }
30219  }
30220 }
30221 
30222 /* inherits documentation from base class */
30223 QPointF QCPItemPixmap::anchorPixelPosition(int anchorId) const
30224 {
30225  bool flipHorz = false;
30226  bool flipVert = false;
30227  QRect rect = getFinalRect(&flipHorz, &flipVert);
30228  // we actually want denormal rects (negative width/height) here, so restore
30229  // the flipped state:
30230  if (flipHorz)
30231  rect.adjust(rect.width(), 0, -rect.width(), 0);
30232  if (flipVert)
30233  rect.adjust(0, rect.height(), 0, -rect.height());
30234 
30235  switch (anchorId)
30236  {
30237  case aiTop: return (rect.topLeft()+rect.topRight())*0.5;
30238  case aiTopRight: return rect.topRight();
30239  case aiRight: return (rect.topRight()+rect.bottomRight())*0.5;
30240  case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5;
30241  case aiBottomLeft: return rect.bottomLeft();
30242  case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;
30243  }
30244 
30245  qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
30246  return {};
30247 }
30248 
30262 void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert)
30263 {
30264  if (mPixmap.isNull())
30265  return;
30266 
30267  if (mScaled)
30268  {
30269 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30270  double devicePixelRatio = mPixmap.devicePixelRatio();
30271 #else
30272  double devicePixelRatio = 1.0;
30273 #endif
30274  if (finalRect.isNull())
30275  finalRect = getFinalRect(&flipHorz, &flipVert);
30276  if (mScaledPixmapInvalidated || finalRect.size() != mScaledPixmap.size()/devicePixelRatio)
30277  {
30278  mScaledPixmap = mPixmap.scaled(finalRect.size()*devicePixelRatio, mAspectRatioMode, mTransformationMode);
30279  if (flipHorz || flipVert)
30280  mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert));
30281 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30282  mScaledPixmap.setDevicePixelRatio(devicePixelRatio);
30283 #endif
30284  }
30285  } else if (!mScaledPixmap.isNull())
30286  mScaledPixmap = QPixmap();
30287  mScaledPixmapInvalidated = false;
30288 }
30289 
30304 QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const
30305 {
30306  QRect result;
30307  bool flipHorz = false;
30308  bool flipVert = false;
30309  QPoint p1 = topLeft->pixelPosition().toPoint();
30310  QPoint p2 = bottomRight->pixelPosition().toPoint();
30311  if (p1 == p2)
30312  return {p1, QSize(0, 0)};
30313  if (mScaled)
30314  {
30315  QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y());
30316  QPoint topLeft = p1;
30317  if (newSize.width() < 0)
30318  {
30319  flipHorz = true;
30320  newSize.rwidth() *= -1;
30321  topLeft.setX(p2.x());
30322  }
30323  if (newSize.height() < 0)
30324  {
30325  flipVert = true;
30326  newSize.rheight() *= -1;
30327  topLeft.setY(p2.y());
30328  }
30329  QSize scaledSize = mPixmap.size();
30330 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30331  scaledSize /= mPixmap.devicePixelRatio();
30332  scaledSize.scale(newSize*mPixmap.devicePixelRatio(), mAspectRatioMode);
30333 #else
30334  scaledSize.scale(newSize, mAspectRatioMode);
30335 #endif
30336  result = QRect(topLeft, scaledSize);
30337  } else
30338  {
30339 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30340  result = QRect(p1, mPixmap.size()/mPixmap.devicePixelRatio());
30341 #else
30342  result = QRect(p1, mPixmap.size());
30343 #endif
30344  }
30345  if (flippedHorz)
30346  *flippedHorz = flipHorz;
30347  if (flippedVert)
30348  *flippedVert = flipVert;
30349  return result;
30350 }
30351 
30358 {
30359  return mSelected ? mSelectedPen : mPen;
30360 }
30361 /* end of 'src/items/item-pixmap.cpp' */
30362 
30363 
30364 /* including file 'src/items/item-tracer.cpp' */
30365 /* modified 2021-03-29T02:30:44, size 14645 */
30366 
30370 
30408  QCPAbstractItem(parentPlot),
30409  position(createPosition(QLatin1String("position"))),
30410  mSize(6),
30411  mStyle(tsCrosshair),
30412  mGraph(nullptr),
30413  mGraphKey(0),
30414  mInterpolating(false)
30415 {
30416  position->setCoords(0, 0);
30417 
30418  setBrush(Qt::NoBrush);
30419  setSelectedBrush(Qt::NoBrush);
30420  setPen(QPen(Qt::black));
30421  setSelectedPen(QPen(Qt::blue, 2));
30422 }
30423 
30425 {
30426 }
30427 
30433 void QCPItemTracer::setPen(const QPen &pen)
30434 {
30435  mPen = pen;
30436 }
30437 
30443 void QCPItemTracer::setSelectedPen(const QPen &pen)
30444 {
30445  mSelectedPen = pen;
30446 }
30447 
30453 void QCPItemTracer::setBrush(const QBrush &brush)
30454 {
30455  mBrush = brush;
30456 }
30457 
30463 void QCPItemTracer::setSelectedBrush(const QBrush &brush)
30464 {
30466 }
30467 
30472 void QCPItemTracer::setSize(double size)
30473 {
30474  mSize = size;
30475 }
30476 
30484 {
30485  mStyle = style;
30486 }
30487 
30499 {
30500  if (graph)
30501  {
30502  if (graph->parentPlot() == mParentPlot)
30503  {
30506  mGraph = graph;
30507  updatePosition();
30508  } else
30509  qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item";
30510  } else
30511  {
30512  mGraph = nullptr;
30513  }
30514 }
30515 
30526 {
30527  mGraphKey = key;
30528 }
30529 
30542 {
30543  mInterpolating = enabled;
30544 }
30545 
30546 /* inherits documentation from base class */
30547 double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
30548 {
30549  Q_UNUSED(details)
30550  if (onlySelectable && !mSelectable)
30551  return -1;
30552 
30553  QPointF center(position->pixelPosition());
30554  double w = mSize/2.0;
30555  QRect clip = clipRect();
30556  switch (mStyle)
30557  {
30558  case tsNone: return -1;
30559  case tsPlus:
30560  {
30561  if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30562  return qSqrt(qMin(QCPVector2D(pos).distanceSquaredToLine(center+QPointF(-w, 0), center+QPointF(w, 0)),
30563  QCPVector2D(pos).distanceSquaredToLine(center+QPointF(0, -w), center+QPointF(0, w))));
30564  break;
30565  }
30566  case tsCrosshair:
30567  {
30568  return qSqrt(qMin(QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(clip.left(), center.y()), QCPVector2D(clip.right(), center.y())),
30569  QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(center.x(), clip.top()), QCPVector2D(center.x(), clip.bottom()))));
30570  }
30571  case tsCircle:
30572  {
30573  if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30574  {
30575  // distance to border:
30576  double centerDist = QCPVector2D(center-pos).length();
30577  double circleLine = w;
30578  double result = qAbs(centerDist-circleLine);
30579  // filled ellipse, allow click inside to count as hit:
30580  if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0)
30581  {
30582  if (centerDist <= circleLine)
30583  result = mParentPlot->selectionTolerance()*0.99;
30584  }
30585  return result;
30586  }
30587  break;
30588  }
30589  case tsSquare:
30590  {
30591  if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30592  {
30593  QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w));
30594  bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0;
30595  return rectDistance(rect, pos, filledRect);
30596  }
30597  break;
30598  }
30599  }
30600  return -1;
30601 }
30602 
30603 /* inherits documentation from base class */
30605 {
30606  updatePosition();
30607  if (mStyle == tsNone)
30608  return;
30609 
30610  painter->setPen(mainPen());
30611  painter->setBrush(mainBrush());
30612  QPointF center(position->pixelPosition());
30613  double w = mSize/2.0;
30614  QRect clip = clipRect();
30615  switch (mStyle)
30616  {
30617  case tsNone: return;
30618  case tsPlus:
30619  {
30620  if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30621  {
30622  painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0)));
30623  painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w)));
30624  }
30625  break;
30626  }
30627  case tsCrosshair:
30628  {
30629  if (center.y() > clip.top() && center.y() < clip.bottom())
30630  painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y()));
30631  if (center.x() > clip.left() && center.x() < clip.right())
30632  painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom()));
30633  break;
30634  }
30635  case tsCircle:
30636  {
30637  if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30638  painter->drawEllipse(center, w, w);
30639  break;
30640  }
30641  case tsSquare:
30642  {
30643  if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30644  painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w)));
30645  break;
30646  }
30647  }
30648 }
30649 
30663 {
30664  if (mGraph)
30665  {
30667  {
30668  if (mGraph->data()->size() > 1)
30669  {
30670  QCPGraphDataContainer::const_iterator first = mGraph->data()->constBegin();
30671  QCPGraphDataContainer::const_iterator last = mGraph->data()->constEnd()-1;
30672  if (mGraphKey <= first->key)
30673  position->setCoords(first->key, first->value);
30674  else if (mGraphKey >= last->key)
30675  position->setCoords(last->key, last->value);
30676  else
30677  {
30679  if (it != mGraph->data()->constEnd()) // mGraphKey is not exactly on last iterator, but somewhere between iterators
30680  {
30682  ++it; // won't advance to constEnd because we handled that case (mGraphKey >= last->key) before
30683  if (mInterpolating)
30684  {
30685  // interpolate between iterators around mGraphKey:
30686  double slope = 0;
30687  if (!qFuzzyCompare(double(it->key), double(prevIt->key)))
30688  slope = (it->value-prevIt->value)/(it->key-prevIt->key);
30689  position->setCoords(mGraphKey, (mGraphKey-prevIt->key)*slope+prevIt->value);
30690  } else
30691  {
30692  // find iterator with key closest to mGraphKey:
30693  if (mGraphKey < (prevIt->key+it->key)*0.5)
30694  position->setCoords(prevIt->key, prevIt->value);
30695  else
30696  position->setCoords(it->key, it->value);
30697  }
30698  } else // mGraphKey is exactly on last iterator (should actually be caught when comparing first/last keys, but this is a failsafe for fp uncertainty)
30699  position->setCoords(it->key, it->value);
30700  }
30701  } else if (mGraph->data()->size() == 1)
30702  {
30703  QCPGraphDataContainer::const_iterator it = mGraph->data()->constBegin();
30704  position->setCoords(it->key, it->value);
30705  } else
30706  qDebug() << Q_FUNC_INFO << "graph has no data";
30707  } else
30708  qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)";
30709  }
30710 }
30711 
30718 {
30719  return mSelected ? mSelectedPen : mPen;
30720 }
30721 
30728 {
30729  return mSelected ? mSelectedBrush : mBrush;
30730 }
30731 /* end of 'src/items/item-tracer.cpp' */
30732 
30733 
30734 /* including file 'src/items/item-bracket.cpp' */
30735 /* modified 2021-03-29T02:30:44, size 10705 */
30736 
30740 
30768  QCPAbstractItem(parentPlot),
30769  left(createPosition(QLatin1String("left"))),
30770  right(createPosition(QLatin1String("right"))),
30771  center(createAnchor(QLatin1String("center"), aiCenter)),
30772  mLength(8),
30773  mStyle(bsCalligraphic)
30774 {
30775  left->setCoords(0, 0);
30776  right->setCoords(1, 1);
30777 
30778  setPen(QPen(Qt::black));
30779  setSelectedPen(QPen(Qt::blue, 2));
30780 }
30781 
30783 {
30784 }
30785 
30795 void QCPItemBracket::setPen(const QPen &pen)
30796 {
30797  mPen = pen;
30798 }
30799 
30805 void QCPItemBracket::setSelectedPen(const QPen &pen)
30806 {
30807  mSelectedPen = pen;
30808 }
30809 
30818 void QCPItemBracket::setLength(double length)
30819 {
30820  mLength = length;
30821 }
30822 
30829 {
30830  mStyle = style;
30831 }
30832 
30833 /* inherits documentation from base class */
30834 double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
30835 {
30836  Q_UNUSED(details)
30837  if (onlySelectable && !mSelectable)
30838  return -1;
30839 
30840  QCPVector2D p(pos);
30841  QCPVector2D leftVec(left->pixelPosition());
30842  QCPVector2D rightVec(right->pixelPosition());
30843  if (leftVec.toPoint() == rightVec.toPoint())
30844  return -1;
30845 
30846  QCPVector2D widthVec = (rightVec-leftVec)*0.5;
30847  QCPVector2D lengthVec = widthVec.perpendicular().normalized()*mLength;
30848  QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec;
30849 
30850  switch (mStyle)
30851  {
30854  {
30855  double a = p.distanceSquaredToLine(centerVec-widthVec, centerVec+widthVec);
30856  double b = p.distanceSquaredToLine(centerVec-widthVec+lengthVec, centerVec-widthVec);
30857  double c = p.distanceSquaredToLine(centerVec+widthVec+lengthVec, centerVec+widthVec);
30858  return qSqrt(qMin(qMin(a, b), c));
30859  }
30862  {
30863  double a = p.distanceSquaredToLine(centerVec-widthVec*0.75+lengthVec*0.15, centerVec+lengthVec*0.3);
30864  double b = p.distanceSquaredToLine(centerVec-widthVec+lengthVec*0.7, centerVec-widthVec*0.75+lengthVec*0.15);
30865  double c = p.distanceSquaredToLine(centerVec+widthVec*0.75+lengthVec*0.15, centerVec+lengthVec*0.3);
30866  double d = p.distanceSquaredToLine(centerVec+widthVec+lengthVec*0.7, centerVec+widthVec*0.75+lengthVec*0.15);
30867  return qSqrt(qMin(qMin(a, b), qMin(c, d)));
30868  }
30869  }
30870  return -1;
30871 }
30872 
30873 /* inherits documentation from base class */
30875 {
30876  QCPVector2D leftVec(left->pixelPosition());
30877  QCPVector2D rightVec(right->pixelPosition());
30878  if (leftVec.toPoint() == rightVec.toPoint())
30879  return;
30880 
30881  QCPVector2D widthVec = (rightVec-leftVec)*0.5;
30882  QCPVector2D lengthVec = widthVec.perpendicular().normalized()*mLength;
30883  QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec;
30884 
30885  QPolygon boundingPoly;
30886  boundingPoly << leftVec.toPoint() << rightVec.toPoint()
30887  << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint();
30888  const int clipEnlarge = qCeil(mainPen().widthF());
30889  QRect clip = clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge);
30890  if (clip.intersects(boundingPoly.boundingRect()))
30891  {
30892  painter->setPen(mainPen());
30893  switch (mStyle)
30894  {
30895  case bsSquare:
30896  {
30897  painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF());
30898  painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
30899  painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30900  break;
30901  }
30902  case bsRound:
30903  {
30904  painter->setBrush(Qt::NoBrush);
30905  QPainterPath path;
30906  path.moveTo((centerVec+widthVec+lengthVec).toPointF());
30907  path.cubicTo((centerVec+widthVec).toPointF(), (centerVec+widthVec).toPointF(), centerVec.toPointF());
30908  path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30909  painter->drawPath(path);
30910  break;
30911  }
30912  case bsCurly:
30913  {
30914  painter->setBrush(Qt::NoBrush);
30915  QPainterPath path;
30916  path.moveTo((centerVec+widthVec+lengthVec).toPointF());
30917  path.cubicTo((centerVec+widthVec-lengthVec*0.8).toPointF(), (centerVec+0.4*widthVec+lengthVec).toPointF(), centerVec.toPointF());
30918  path.cubicTo((centerVec-0.4*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30919  painter->drawPath(path);
30920  break;
30921  }
30922  case bsCalligraphic:
30923  {
30924  painter->setPen(Qt::NoPen);
30925  painter->setBrush(QBrush(mainPen().color()));
30926  QPainterPath path;
30927  path.moveTo((centerVec+widthVec+lengthVec).toPointF());
30928 
30929  path.cubicTo((centerVec+widthVec-lengthVec*0.8).toPointF(), (centerVec+0.4*widthVec+0.8*lengthVec).toPointF(), centerVec.toPointF());
30930  path.cubicTo((centerVec-0.4*widthVec+0.8*lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30931 
30932  path.cubicTo((centerVec-widthVec-lengthVec*0.5).toPointF(), (centerVec-0.2*widthVec+1.2*lengthVec).toPointF(), (centerVec+lengthVec*0.2).toPointF());
30933  path.cubicTo((centerVec+0.2*widthVec+1.2*lengthVec).toPointF(), (centerVec+widthVec-lengthVec*0.5).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
30934 
30935  painter->drawPath(path);
30936  break;
30937  }
30938  }
30939  }
30940 }
30941 
30942 /* inherits documentation from base class */
30943 QPointF QCPItemBracket::anchorPixelPosition(int anchorId) const
30944 {
30945  QCPVector2D leftVec(left->pixelPosition());
30946  QCPVector2D rightVec(right->pixelPosition());
30947  if (leftVec.toPoint() == rightVec.toPoint())
30948  return leftVec.toPointF();
30949 
30950  QCPVector2D widthVec = (rightVec-leftVec)*0.5;
30951  QCPVector2D lengthVec = widthVec.perpendicular().normalized()*mLength;
30952  QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec;
30953 
30954  switch (anchorId)
30955  {
30956  case aiCenter:
30957  return centerVec.toPointF();
30958  }
30959  qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId;
30960  return {};
30961 }
30962 
30969 {
30970  return mSelected ? mSelectedPen : mPen;
30971 }
30972 /* end of 'src/items/item-bracket.cpp' */
30973 
30974 
30975 /* including file 'src/polar/radialaxis.cpp' */
30976 /* modified 2021-03-29T02:30:44, size 49415 */
30977 
30978 
30979 
30983 
30996 /* start of documentation of inline functions */
30997 
31014 /* end of documentation of inline functions */
31015 /* start of documentation of signals */
31016 
31055 /* end of documentation of signals */
31056 
31065  QCPLayerable(parent->parentPlot(), QString(), parent),
31066  mRangeDrag(true),
31067  mRangeZoom(true),
31068  mRangeZoomFactor(0.85),
31069  // axis base:
31070  mAngularAxis(parent),
31071  mAngle(45),
31072  mAngleReference(arAngularAxis),
31073  mSelectableParts(spAxis | spTickLabels | spAxisLabel),
31074  mSelectedParts(spNone),
31075  mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
31076  mSelectedBasePen(QPen(Qt::blue, 2)),
31077  // axis label:
31078  mLabelPadding(0),
31079  mLabel(),
31080  mLabelFont(mParentPlot->font()),
31081  mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
31082  mLabelColor(Qt::black),
31083  mSelectedLabelColor(Qt::blue),
31084  // tick labels:
31085  // mTickLabelPadding(0), in label painter
31086  mTickLabels(true),
31087  // mTickLabelRotation(0), in label painter
31088  mTickLabelFont(mParentPlot->font()),
31089  mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
31090  mTickLabelColor(Qt::black),
31091  mSelectedTickLabelColor(Qt::blue),
31092  mNumberPrecision(6),
31093  mNumberFormatChar('g'),
31094  mNumberBeautifulPowers(true),
31095  mNumberMultiplyCross(false),
31096  // ticks and subticks:
31097  mTicks(true),
31098  mSubTicks(true),
31099  mTickLengthIn(5),
31100  mTickLengthOut(0),
31101  mSubTickLengthIn(2),
31102  mSubTickLengthOut(0),
31103  mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
31104  mSelectedTickPen(QPen(Qt::blue, 2)),
31105  mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
31106  mSelectedSubTickPen(QPen(Qt::blue, 2)),
31107  // scale and range:
31108  mRange(0, 5),
31109  mRangeReversed(false),
31110  mScaleType(stLinear),
31111  // internal members:
31112  mRadius(1), // non-zero initial value, will be overwritten in ::update() according to inner rect
31113  mTicker(new QCPAxisTicker),
31114  mLabelPainter(mParentPlot)
31115 {
31116  setParent(parent);
31117  setAntialiased(true);
31118 
31124 }
31125 
31127 {
31128 }
31129 
31131 {
31132  switch (mLabelPainter.anchorMode())
31133  {
31136  default: qDebug() << Q_FUNC_INFO << "invalid mode for polar axis"; break;
31137  }
31138  return lmUpright;
31139 }
31140 
31141 /* No documentation as it is a property getter */
31143 {
31144  QString result;
31145  result.append(mNumberFormatChar);
31147  {
31148  result.append(QLatin1Char('b'));
31150  result.append(QLatin1Char('c'));
31151  }
31152  return result;
31153 }
31154 
31155 /* No documentation as it is a property getter */
31157 {
31158  return mTickLengthIn;
31159 }
31160 
31161 /* No documentation as it is a property getter */
31163 {
31164  return mTickLengthOut;
31165 }
31166 
31167 /* No documentation as it is a property getter */
31169 {
31170  return mSubTickLengthIn;
31171 }
31172 
31173 /* No documentation as it is a property getter */
31175 {
31176  return mSubTickLengthOut;
31177 }
31178 
31179 /* No documentation as it is a property getter */
31181 {
31182  return mLabelPadding;
31183 }
31184 
31186 {
31187  mRangeDrag = enabled;
31188 }
31189 
31191 {
31192  mRangeZoom = enabled;
31193 }
31194 
31196 {
31197  mRangeZoomFactor = factor;
31198 }
31199 
31215 {
31216  if (mScaleType != type)
31217  {
31218  mScaleType = type;
31219  if (mScaleType == stLogarithmic)
31221  //mCachedMarginValid = false;
31223  }
31224 }
31225 
31235 {
31236  if (range.lower == mRange.lower && range.upper == mRange.upper)
31237  return;
31238 
31239  if (!QCPRange::validRange(range)) return;
31240  QCPRange oldRange = mRange;
31241  if (mScaleType == stLogarithmic)
31242  {
31244  } else
31245  {
31247  }
31248  emit rangeChanged(mRange);
31249  emit rangeChanged(mRange, oldRange);
31250 }
31251 
31262 void QCPPolarAxisRadial::setSelectableParts(const SelectableParts &selectable)
31263 {
31264  if (mSelectableParts != selectable)
31265  {
31266  mSelectableParts = selectable;
31268  }
31269 }
31270 
31286 void QCPPolarAxisRadial::setSelectedParts(const SelectableParts &selected)
31287 {
31288  if (mSelectedParts != selected)
31289  {
31290  mSelectedParts = selected;
31292  }
31293 }
31294 
31304 void QCPPolarAxisRadial::setRange(double lower, double upper)
31305 {
31306  if (lower == mRange.lower && upper == mRange.upper)
31307  return;
31308 
31309  if (!QCPRange::validRange(lower, upper)) return;
31310  QCPRange oldRange = mRange;
31311  mRange.lower = lower;
31312  mRange.upper = upper;
31313  if (mScaleType == stLogarithmic)
31314  {
31316  } else
31317  {
31319  }
31320  emit rangeChanged(mRange);
31321  emit rangeChanged(mRange, oldRange);
31322 }
31323 
31335 void QCPPolarAxisRadial::setRange(double position, double size, Qt::AlignmentFlag alignment)
31336 {
31337  if (alignment == Qt::AlignLeft)
31338  setRange(position, position+size);
31339  else if (alignment == Qt::AlignRight)
31340  setRange(position-size, position);
31341  else // alignment == Qt::AlignCenter
31342  setRange(position-size/2.0, position+size/2.0);
31343 }
31344 
31350 {
31351  if (mRange.lower == lower)
31352  return;
31353 
31354  QCPRange oldRange = mRange;
31355  mRange.lower = lower;
31356  if (mScaleType == stLogarithmic)
31357  {
31359  } else
31360  {
31362  }
31363  emit rangeChanged(mRange);
31364  emit rangeChanged(mRange, oldRange);
31365 }
31366 
31372 {
31373  if (mRange.upper == upper)
31374  return;
31375 
31376  QCPRange oldRange = mRange;
31377  mRange.upper = upper;
31378  if (mScaleType == stLogarithmic)
31379  {
31381  } else
31382  {
31384  }
31385  emit rangeChanged(mRange);
31386  emit rangeChanged(mRange, oldRange);
31387 }
31388 
31399 {
31400  mRangeReversed = reversed;
31401 }
31402 
31403 void QCPPolarAxisRadial::setAngle(double degrees)
31404 {
31405  mAngle = degrees;
31406 }
31407 
31409 {
31410  mAngleReference = reference;
31411 }
31412 
31426 void QCPPolarAxisRadial::setTicker(QSharedPointer<QCPAxisTicker> ticker)
31427 {
31428  if (ticker)
31429  mTicker = ticker;
31430  else
31431  qDebug() << Q_FUNC_INFO << "can not set 0 as axis ticker";
31432  // no need to invalidate margin cache here because produced tick labels are checked for changes in setupTickVector
31433 }
31434 
31444 {
31445  if (mTicks != show)
31446  {
31447  mTicks = show;
31448  //mCachedMarginValid = false;
31449  }
31450 }
31451 
31456 {
31457  if (mTickLabels != show)
31458  {
31459  mTickLabels = show;
31460  //mCachedMarginValid = false;
31461  if (!mTickLabels)
31462  mTickVectorLabels.clear();
31463  }
31464 }
31465 
31471 {
31472  mLabelPainter.setPadding(padding);
31473 }
31474 
31481 {
31482  if (font != mTickLabelFont)
31483  {
31484  mTickLabelFont = font;
31485  //mCachedMarginValid = false;
31486  }
31487 }
31488 
31495 {
31497 }
31498 
31509 {
31510  mLabelPainter.setRotation(degrees);
31511 }
31512 
31514 {
31515  switch (mode)
31516  {
31519  }
31520 }
31521 
31552 void QCPPolarAxisRadial::setNumberFormat(const QString &formatCode)
31553 {
31554  if (formatCode.isEmpty())
31555  {
31556  qDebug() << Q_FUNC_INFO << "Passed formatCode is empty";
31557  return;
31558  }
31559  //mCachedMarginValid = false;
31560 
31561  // interpret first char as number format char:
31562  QString allowedFormatChars(QLatin1String("eEfgG"));
31563  if (allowedFormatChars.contains(formatCode.at(0)))
31564  {
31565  mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1());
31566  } else
31567  {
31568  qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode;
31569  return;
31570  }
31571 
31572  if (formatCode.length() < 2)
31573  {
31574  mNumberBeautifulPowers = false;
31575  mNumberMultiplyCross = false;
31576  } else
31577  {
31578  // interpret second char as indicator for beautiful decimal powers:
31579  if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g')))
31580  mNumberBeautifulPowers = true;
31581  else
31582  qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
31583 
31584  if (formatCode.length() < 3)
31585  {
31586  mNumberMultiplyCross = false;
31587  } else
31588  {
31589  // interpret third char as indicator for dot or cross multiplication symbol:
31590  if (formatCode.at(2) == QLatin1Char('c'))
31591  mNumberMultiplyCross = true;
31592  else if (formatCode.at(2) == QLatin1Char('d'))
31593  mNumberMultiplyCross = false;
31594  else
31595  qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
31596  }
31597  }
31600 }
31601 
31608 {
31609  if (mNumberPrecision != precision)
31610  {
31611  mNumberPrecision = precision;
31612  //mCachedMarginValid = false;
31613  }
31614 }
31615 
31624 void QCPPolarAxisRadial::setTickLength(int inside, int outside)
31625 {
31626  setTickLengthIn(inside);
31627  setTickLengthOut(outside);
31628 }
31629 
31637 {
31638  if (mTickLengthIn != inside)
31639  {
31640  mTickLengthIn = inside;
31641  }
31642 }
31643 
31652 {
31653  if (mTickLengthOut != outside)
31654  {
31655  mTickLengthOut = outside;
31656  //mCachedMarginValid = false; // only outside tick length can change margin
31657  }
31658 }
31659 
31668 {
31669  if (mSubTicks != show)
31670  {
31671  mSubTicks = show;
31672  //mCachedMarginValid = false;
31673  }
31674 }
31675 
31684 void QCPPolarAxisRadial::setSubTickLength(int inside, int outside)
31685 {
31686  setSubTickLengthIn(inside);
31687  setSubTickLengthOut(outside);
31688 }
31689 
31697 {
31698  if (mSubTickLengthIn != inside)
31699  {
31700  mSubTickLengthIn = inside;
31701  }
31702 }
31703 
31712 {
31713  if (mSubTickLengthOut != outside)
31714  {
31715  mSubTickLengthOut = outside;
31716  //mCachedMarginValid = false; // only outside tick length can change margin
31717  }
31718 }
31719 
31725 void QCPPolarAxisRadial::setBasePen(const QPen &pen)
31726 {
31727  mBasePen = pen;
31728 }
31729 
31735 void QCPPolarAxisRadial::setTickPen(const QPen &pen)
31736 {
31737  mTickPen = pen;
31738 }
31739 
31746 {
31747  mSubTickPen = pen;
31748 }
31749 
31755 void QCPPolarAxisRadial::setLabelFont(const QFont &font)
31756 {
31757  if (mLabelFont != font)
31758  {
31759  mLabelFont = font;
31760  //mCachedMarginValid = false;
31761  }
31762 }
31763 
31770 {
31771  mLabelColor = color;
31772 }
31773 
31778 void QCPPolarAxisRadial::setLabel(const QString &str)
31779 {
31780  if (mLabel != str)
31781  {
31782  mLabel = str;
31783  //mCachedMarginValid = false;
31784  }
31785 }
31786 
31793 {
31794  if (mLabelPadding != padding)
31795  {
31796  mLabelPadding = padding;
31797  //mCachedMarginValid = false;
31798  }
31799 }
31800 
31807 {
31808  if (font != mSelectedTickLabelFont)
31809  {
31810  mSelectedTickLabelFont = font;
31811  // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
31812  }
31813 }
31814 
31821 {
31822  mSelectedLabelFont = font;
31823  // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
31824 }
31825 
31832 {
31834  {
31836  }
31837 }
31838 
31845 {
31847 }
31848 
31855 {
31856  mSelectedBasePen = pen;
31857 }
31858 
31865 {
31866  mSelectedTickPen = pen;
31867 }
31868 
31875 {
31876  mSelectedSubTickPen = pen;
31877 }
31878 
31887 {
31888  QCPRange oldRange = mRange;
31889  if (mScaleType == stLinear)
31890  {
31891  mRange.lower += diff;
31892  mRange.upper += diff;
31893  } else // mScaleType == stLogarithmic
31894  {
31895  mRange.lower *= diff;
31896  mRange.upper *= diff;
31897  }
31898  emit rangeChanged(mRange);
31899  emit rangeChanged(mRange, oldRange);
31900 }
31901 
31912 {
31913  scaleRange(factor, range().center());
31914 }
31915 
31925 void QCPPolarAxisRadial::scaleRange(double factor, double center)
31926 {
31927  QCPRange oldRange = mRange;
31928  if (mScaleType == stLinear)
31929  {
31930  QCPRange newRange;
31931  newRange.lower = (mRange.lower-center)*factor + center;
31932  newRange.upper = (mRange.upper-center)*factor + center;
31933  if (QCPRange::validRange(newRange))
31934  mRange = newRange.sanitizedForLinScale();
31935  } else // mScaleType == stLogarithmic
31936  {
31937  if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range
31938  {
31939  QCPRange newRange;
31940  newRange.lower = qPow(mRange.lower/center, factor)*center;
31941  newRange.upper = qPow(mRange.upper/center, factor)*center;
31942  if (QCPRange::validRange(newRange))
31943  mRange = newRange.sanitizedForLogScale();
31944  } else
31945  qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
31946  }
31947  emit rangeChanged(mRange);
31948  emit rangeChanged(mRange, oldRange);
31949 }
31950 
31957 void QCPPolarAxisRadial::rescale(bool onlyVisiblePlottables)
31958 {
31959  Q_UNUSED(onlyVisiblePlottables)
31960  /* TODO
31961  QList<QCPAbstractPlottable*> p = plottables();
31962  QCPRange newRange;
31963  bool haveRange = false;
31964  for (int i=0; i<p.size(); ++i)
31965  {
31966  if (!p.at(i)->realVisibility() && onlyVisiblePlottables)
31967  continue;
31968  QCPRange plottableRange;
31969  bool currentFoundRange;
31970  QCP::SignDomain signDomain = QCP::sdBoth;
31971  if (mScaleType == stLogarithmic)
31972  signDomain = (mRange.upper < 0 ? QCP::sdNegative : QCP::sdPositive);
31973  if (p.at(i)->keyAxis() == this)
31974  plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain);
31975  else
31976  plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain);
31977  if (currentFoundRange)
31978  {
31979  if (!haveRange)
31980  newRange = plottableRange;
31981  else
31982  newRange.expand(plottableRange);
31983  haveRange = true;
31984  }
31985  }
31986  if (haveRange)
31987  {
31988  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
31989  {
31990  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
31991  if (mScaleType == stLinear)
31992  {
31993  newRange.lower = center-mRange.size()/2.0;
31994  newRange.upper = center+mRange.size()/2.0;
31995  } else // mScaleType == stLogarithmic
31996  {
31997  newRange.lower = center/qSqrt(mRange.upper/mRange.lower);
31998  newRange.upper = center*qSqrt(mRange.upper/mRange.lower);
31999  }
32000  }
32001  setRange(newRange);
32002  }
32003  */
32004 }
32005 
32009 void QCPPolarAxisRadial::pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const
32010 {
32011  QCPVector2D posVector(pixelPos-mCenter);
32012  radiusCoord = radiusToCoord(posVector.length());
32013  angleCoord = mAngularAxis->angleRadToCoord(posVector.angle());
32014 }
32015 
32019 QPointF QCPPolarAxisRadial::coordToPixel(double angleCoord, double radiusCoord) const
32020 {
32021  const double radiusPixel = coordToRadius(radiusCoord);
32022  const double angleRad = mAngularAxis->coordToAngleRad(angleCoord);
32023  return QPointF(mCenter.x()+qCos(angleRad)*radiusPixel, mCenter.y()+qSin(angleRad)*radiusPixel);
32024 }
32025 
32026 double QCPPolarAxisRadial::coordToRadius(double coord) const
32027 {
32028  if (mScaleType == stLinear)
32029  {
32030  if (!mRangeReversed)
32031  return (coord-mRange.lower)/mRange.size()*mRadius;
32032  else
32033  return (mRange.upper-coord)/mRange.size()*mRadius;
32034  } else // mScaleType == stLogarithmic
32035  {
32036  if (coord >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just return outside visible range
32037  return !mRangeReversed ? mRadius+200 : mRadius-200;
32038  else if (coord <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, just return outside visible range
32039  return !mRangeReversed ? mRadius-200 :mRadius+200;
32040  else
32041  {
32042  if (!mRangeReversed)
32043  return qLn(coord/mRange.lower)/qLn(mRange.upper/mRange.lower)*mRadius;
32044  else
32045  return qLn(mRange.upper/coord)/qLn(mRange.upper/mRange.lower)*mRadius;
32046  }
32047  }
32048 }
32049 
32050 double QCPPolarAxisRadial::radiusToCoord(double radius) const
32051 {
32052  if (mScaleType == stLinear)
32053  {
32054  if (!mRangeReversed)
32055  return (radius)/mRadius*mRange.size()+mRange.lower;
32056  else
32057  return -(radius)/mRadius*mRange.size()+mRange.upper;
32058  } else // mScaleType == stLogarithmic
32059  {
32060  if (!mRangeReversed)
32061  return qPow(mRange.upper/mRange.lower, (radius)/mRadius)*mRange.lower;
32062  else
32063  return qPow(mRange.upper/mRange.lower, (-radius)/mRadius)*mRange.upper;
32064  }
32065 }
32066 
32067 
32078 {
32079  Q_UNUSED(pos) // TODO remove later
32080  if (!mVisible)
32081  return spNone;
32082 
32083  /*
32084  TODO:
32085  if (mAxisPainter->axisSelectionBox().contains(pos.toPoint()))
32086  return spAxis;
32087  else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint()))
32088  return spTickLabels;
32089  else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint()))
32090  return spAxisLabel;
32091  else */
32092  return spNone;
32093 }
32094 
32095 /* inherits documentation from base class */
32096 double QCPPolarAxisRadial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
32097 {
32098  if (!mParentPlot) return -1;
32099  SelectablePart part = getPartAt(pos);
32100  if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone)
32101  return -1;
32102 
32103  if (details)
32104  details->setValue(part);
32105  return mParentPlot->selectionTolerance()*0.99;
32106 }
32107 
32108 /* inherits documentation from base class */
32109 void QCPPolarAxisRadial::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
32110 {
32111  Q_UNUSED(event)
32112  SelectablePart part = details.value<SelectablePart>();
32113  if (mSelectableParts.testFlag(part))
32114  {
32115  SelectableParts selBefore = mSelectedParts;
32116  setSelectedParts(additive ? mSelectedParts^part : part);
32117  if (selectionStateChanged)
32118  *selectionStateChanged = mSelectedParts != selBefore;
32119  }
32120 }
32121 
32122 /* inherits documentation from base class */
32123 void QCPPolarAxisRadial::deselectEvent(bool *selectionStateChanged)
32124 {
32125  SelectableParts selBefore = mSelectedParts;
32127  if (selectionStateChanged)
32128  *selectionStateChanged = mSelectedParts != selBefore;
32129 }
32130 
32146 void QCPPolarAxisRadial::mousePressEvent(QMouseEvent *event, const QVariant &details)
32147 {
32148  Q_UNUSED(details)
32149  if (!mParentPlot->interactions().testFlag(QCP::iRangeDrag))
32150  {
32151  event->ignore();
32152  return;
32153  }
32154 
32155  if (event->buttons() & Qt::LeftButton)
32156  {
32157  mDragging = true;
32158  // initialize antialiasing backup in case we start dragging:
32160  {
32163  }
32164  // Mouse range dragging interaction:
32165  if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
32167  }
32168 }
32169 
32182 void QCPPolarAxisRadial::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
32183 {
32184  Q_UNUSED(event) // TODO remove later
32185  Q_UNUSED(startPos) // TODO remove later
32186  if (mDragging)
32187  {
32188  /* TODO
32189  const double startPixel = orientation() == Qt::Horizontal ? startPos.x() : startPos.y();
32190  const double currentPixel = orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y();
32191  if (mScaleType == QCPPolarAxisRadial::stLinear)
32192  {
32193  const double diff = pixelToCoord(startPixel) - pixelToCoord(currentPixel);
32194  setRange(mDragStartRange.lower+diff, mDragStartRange.upper+diff);
32195  } else if (mScaleType == QCPPolarAxisRadial::stLogarithmic)
32196  {
32197  const double diff = pixelToCoord(startPixel) / pixelToCoord(currentPixel);
32198  setRange(mDragStartRange.lower*diff, mDragStartRange.upper*diff);
32199  }
32200  */
32201 
32205  }
32206 }
32207 
32220 void QCPPolarAxisRadial::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
32221 {
32222  Q_UNUSED(event)
32223  Q_UNUSED(startPos)
32224  mDragging = false;
32226  {
32229  }
32230 }
32231 
32247 void QCPPolarAxisRadial::wheelEvent(QWheelEvent *event)
32248 {
32249  // Mouse range zooming interaction:
32250  if (!mParentPlot->interactions().testFlag(QCP::iRangeZoom))
32251  {
32252  event->ignore();
32253  return;
32254  }
32255 
32256  // TODO:
32257  //const double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually
32258  //const double factor = qPow(mRangeZoomFactor, wheelSteps);
32259  //scaleRange(factor, pixelToCoord(orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y()));
32260  mParentPlot->replot();
32261 }
32262 
32263 void QCPPolarAxisRadial::updateGeometry(const QPointF &center, double radius)
32264 {
32265  mCenter = center;
32266  mRadius = radius;
32267  if (mRadius < 1) mRadius = 1;
32268 }
32269 
32286 {
32288 }
32289 
32297 {
32298  const double axisAngleRad = (mAngle+(mAngleReference==arAngularAxis ? mAngularAxis->angle() : 0))/180.0*M_PI;
32299  const QPointF axisVector(qCos(axisAngleRad), qSin(axisAngleRad)); // semantically should be QCPVector2D, but we save time in loops when we keep it as QPointF
32300  const QPointF tickNormal = QCPVector2D(axisVector).perpendicular().toPointF(); // semantically should be QCPVector2D, but we save time in loops when we keep it as QPointF
32301 
32302  // draw baseline:
32303  painter->setPen(getBasePen());
32304  painter->drawLine(QLineF(mCenter, mCenter+axisVector*(mRadius-0.5)));
32305 
32306  // draw subticks:
32307  if (!mSubTickVector.isEmpty())
32308  {
32309  painter->setPen(getSubTickPen());
32310  for (int i=0; i<mSubTickVector.size(); ++i)
32311  {
32312  const QPointF tickPosition = mCenter+axisVector*coordToRadius(mSubTickVector.at(i));
32313  painter->drawLine(QLineF(tickPosition-tickNormal*mSubTickLengthIn, tickPosition+tickNormal*mSubTickLengthOut));
32314  }
32315  }
32316 
32317  // draw ticks and labels:
32318  if (!mTickVector.isEmpty())
32319  {
32320  mLabelPainter.setAnchorReference(mCenter-axisVector); // subtract (normalized) axisVector, just to prevent degenerate tangents for tick label at exact lower axis range
32323  const QPen ticksPen = getTickPen();
32324  painter->setPen(ticksPen);
32325  for (int i=0; i<mTickVector.size(); ++i)
32326  {
32327  const double r = coordToRadius(mTickVector.at(i));
32328  const QPointF tickPosition = mCenter+axisVector*r;
32329  painter->drawLine(QLineF(tickPosition-tickNormal*mTickLengthIn, tickPosition+tickNormal*mTickLengthOut));
32330  // possibly draw tick labels:
32331  if (!mTickVectorLabels.isEmpty())
32332  {
32333  if ((!mRangeReversed && (i < mTickVectorLabels.count()-1 || mRadius-r > 10)) ||
32334  (mRangeReversed && (i > 0 || mRadius-r > 10))) // skip last label if it's closer than 10 pixels to angular axis
32335  mLabelPainter.drawTickLabel(painter, tickPosition+tickNormal*mSubTickLengthOut, mTickVectorLabels.at(i));
32336  }
32337  }
32338  }
32339 }
32340 
32350 {
32351  if (!mParentPlot) return;
32352  if ((!mTicks && !mTickLabels) || mRange.size() <= 0) return;
32353 
32355 }
32356 
32363 {
32364  return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen;
32365 }
32366 
32373 {
32374  return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen;
32375 }
32376 
32383 {
32385 }
32386 
32393 {
32395 }
32396 
32403 {
32405 }
32406 
32413 {
32415 }
32416 
32423 {
32425 }
32426 
32427 
32428 /* inherits documentation from base class */
32430 {
32431  return QCP::iSelectAxes;
32432 }
32433 /* end of 'src/polar/radialaxis.cpp' */
32434 
32435 
32436 /* including file 'src/polar/layoutelement-angularaxis.cpp' */
32437 /* modified 2021-03-29T02:30:44, size 57266 */
32438 
32439 
32443 
32451 /* start documentation of inline functions */
32452 
32533 /* end documentation of inline functions */
32534 
32540  QCPLayoutElement(parentPlot),
32541  mBackgroundBrush(Qt::NoBrush),
32542  mBackgroundScaled(true),
32543  mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
32544  mInsetLayout(new QCPLayoutInset),
32545  mRangeDrag(false),
32546  mRangeZoom(false),
32547  mRangeZoomFactor(0.85),
32548  // axis base:
32549  mAngle(-90),
32550  mAngleRad(mAngle/180.0*M_PI),
32551  mSelectableParts(spAxis | spTickLabels | spAxisLabel),
32552  mSelectedParts(spNone),
32553  mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
32554  mSelectedBasePen(QPen(Qt::blue, 2)),
32555  // axis label:
32556  mLabelPadding(0),
32557  mLabel(),
32558  mLabelFont(mParentPlot->font()),
32559  mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
32560  mLabelColor(Qt::black),
32561  mSelectedLabelColor(Qt::blue),
32562  // tick labels:
32563  //mTickLabelPadding(0), in label painter
32564  mTickLabels(true),
32565  //mTickLabelRotation(0), in label painter
32566  mTickLabelFont(mParentPlot->font()),
32567  mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
32568  mTickLabelColor(Qt::black),
32569  mSelectedTickLabelColor(Qt::blue),
32570  mNumberPrecision(6),
32571  mNumberFormatChar('g'),
32572  mNumberBeautifulPowers(true),
32573  mNumberMultiplyCross(false),
32574  // ticks and subticks:
32575  mTicks(true),
32576  mSubTicks(true),
32577  mTickLengthIn(5),
32578  mTickLengthOut(0),
32579  mSubTickLengthIn(2),
32580  mSubTickLengthOut(0),
32581  mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
32582  mSelectedTickPen(QPen(Qt::blue, 2)),
32583  mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
32584  mSelectedSubTickPen(QPen(Qt::blue, 2)),
32585  // scale and range:
32586  mRange(0, 360),
32587  mRangeReversed(false),
32588  // internal members:
32589  mRadius(1), // non-zero initial value, will be overwritten in ::update() according to inner rect
32590  mGrid(new QCPPolarGrid(this)),
32591  mTicker(new QCPAxisTickerFixed),
32592  mDragging(false),
32593  mLabelPainter(parentPlot)
32594 {
32595  // TODO:
32596  //mInsetLayout->initializeParentPlot(mParentPlot);
32597  //mInsetLayout->setParentLayerable(this);
32598  //mInsetLayout->setParent(this);
32599 
32600  if (QCPAxisTickerFixed *fixedTicker = mTicker.dynamicCast<QCPAxisTickerFixed>().data())
32601  {
32602  fixedTicker->setTickStep(30);
32603  }
32604  setAntialiased(true);
32605  setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again
32606 
32612  mLabelPainter.setCacheSize(24); // so we can cache up to 15-degree intervals, polar angular axis uses a bit larger cache than normal axes
32613 
32614  setMinimumSize(50, 50);
32615  setMinimumMargins(QMargins(30, 30, 30, 30));
32616 
32617  addRadialAxis();
32619 }
32620 
32622 {
32623  delete mGrid; // delete grid here instead of via parent ~QObject for better defined deletion order
32624  mGrid = 0;
32625 
32626  delete mInsetLayout;
32627  mInsetLayout = 0;
32628 
32629  QList<QCPPolarAxisRadial*> radialAxesList = radialAxes();
32630  for (int i=0; i<radialAxesList.size(); ++i)
32631  removeRadialAxis(radialAxesList.at(i));
32632 }
32633 
32635 {
32636  switch (mLabelPainter.anchorMode())
32637  {
32640  default: qDebug() << Q_FUNC_INFO << "invalid mode for polar axis"; break;
32641  }
32642  return lmUpright;
32643 }
32644 
32645 /* No documentation as it is a property getter */
32647 {
32648  QString result;
32649  result.append(mNumberFormatChar);
32651  {
32652  result.append(QLatin1Char('b'));
32654  result.append(QLatin1Char('c'));
32655  }
32656  return result;
32657 }
32658 
32665 {
32666  return mRadialAxes.size();
32667 }
32668 
32675 {
32676  if (index >= 0 && index < mRadialAxes.size())
32677  {
32678  return mRadialAxes.at(index);
32679  } else
32680  {
32681  qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index;
32682  return 0;
32683  }
32684 }
32685 
32694 QList<QCPPolarAxisRadial*> QCPPolarAxisAngular::radialAxes() const
32695 {
32696  return mRadialAxes;
32697 }
32698 
32699 
32721 {
32722  QCPPolarAxisRadial *newAxis = axis;
32723  if (!newAxis)
32724  {
32725  newAxis = new QCPPolarAxisRadial(this);
32726  } else // user provided existing axis instance, do some sanity checks
32727  {
32728  if (newAxis->angularAxis() != this)
32729  {
32730  qDebug() << Q_FUNC_INFO << "passed radial axis doesn't have this angular axis as parent angular axis";
32731  return 0;
32732  }
32733  if (radialAxes().contains(newAxis))
32734  {
32735  qDebug() << Q_FUNC_INFO << "passed axis is already owned by this angular axis";
32736  return 0;
32737  }
32738  }
32739  mRadialAxes.append(newAxis);
32740  return newAxis;
32741 }
32742 
32751 {
32752  if (mRadialAxes.contains(radialAxis))
32753  {
32754  mRadialAxes.removeOne(radialAxis);
32755  delete radialAxis;
32756  return true;
32757  } else
32758  {
32759  qDebug() << Q_FUNC_INFO << "Radial axis isn't associated with this angular axis:" << reinterpret_cast<quintptr>(radialAxis);
32760  return false;
32761  }
32762 }
32763 
32765 {
32766  return QRegion(mCenter.x()-mRadius, mCenter.y()-mRadius, qRound(2*mRadius), qRound(2*mRadius), QRegion::Ellipse);
32767 }
32768 
32777 {
32778  QCPRange oldRange = mRange;
32779  mRange.lower += diff;
32780  mRange.upper += diff;
32781  emit rangeChanged(mRange);
32782  emit rangeChanged(mRange, oldRange);
32783 }
32784 
32795 {
32796  scaleRange(factor, range().center());
32797 }
32798 
32808 void QCPPolarAxisAngular::scaleRange(double factor, double center)
32809 {
32810  QCPRange oldRange = mRange;
32811  QCPRange newRange;
32812  newRange.lower = (mRange.lower-center)*factor + center;
32813  newRange.upper = (mRange.upper-center)*factor + center;
32814  if (QCPRange::validRange(newRange))
32815  mRange = newRange.sanitizedForLinScale();
32816  emit rangeChanged(mRange);
32817  emit rangeChanged(mRange, oldRange);
32818 }
32819 
32826 void QCPPolarAxisAngular::rescale(bool onlyVisiblePlottables)
32827 {
32828  QCPRange newRange;
32829  bool haveRange = false;
32830  for (int i=0; i<mGraphs.size(); ++i)
32831  {
32832  if (!mGraphs.at(i)->realVisibility() && onlyVisiblePlottables)
32833  continue;
32834  QCPRange range;
32835  bool currentFoundRange;
32836  if (mGraphs.at(i)->keyAxis() == this)
32837  range = mGraphs.at(i)->getKeyRange(currentFoundRange, QCP::sdBoth);
32838  else
32839  range = mGraphs.at(i)->getValueRange(currentFoundRange, QCP::sdBoth);
32840  if (currentFoundRange)
32841  {
32842  if (!haveRange)
32843  newRange = range;
32844  else
32845  newRange.expand(range);
32846  haveRange = true;
32847  }
32848  }
32849  if (haveRange)
32850  {
32851  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
32852  {
32853  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
32854  newRange.lower = center-mRange.size()/2.0;
32855  newRange.upper = center+mRange.size()/2.0;
32856  }
32857  setRange(newRange);
32858  }
32859 }
32860 
32864 void QCPPolarAxisAngular::pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const
32865 {
32866  if (!mRadialAxes.isEmpty())
32867  mRadialAxes.first()->pixelToCoord(pixelPos, angleCoord, radiusCoord);
32868  else
32869  qDebug() << Q_FUNC_INFO << "no radial axis configured";
32870 }
32871 
32875 QPointF QCPPolarAxisAngular::coordToPixel(double angleCoord, double radiusCoord) const
32876 {
32877  if (!mRadialAxes.isEmpty())
32878  {
32879  return mRadialAxes.first()->coordToPixel(angleCoord, radiusCoord);
32880  } else
32881  {
32882  qDebug() << Q_FUNC_INFO << "no radial axis configured";
32883  return QPointF();
32884  }
32885 }
32886 
32897 {
32898  Q_UNUSED(pos) // TODO remove later
32899 
32900  if (!mVisible)
32901  return spNone;
32902 
32903  /*
32904  TODO:
32905  if (mAxisPainter->axisSelectionBox().contains(pos.toPoint()))
32906  return spAxis;
32907  else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint()))
32908  return spTickLabels;
32909  else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint()))
32910  return spAxisLabel;
32911  else */
32912  return spNone;
32913 }
32914 
32915 /* inherits documentation from base class */
32916 double QCPPolarAxisAngular::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
32917 {
32918  /*
32919  if (!mParentPlot) return -1;
32920  SelectablePart part = getPartAt(pos);
32921  if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone)
32922  return -1;
32923 
32924  if (details)
32925  details->setValue(part);
32926  return mParentPlot->selectionTolerance()*0.99;
32927  */
32928 
32929  Q_UNUSED(details)
32930 
32931  if (onlySelectable)
32932  return -1;
32933 
32934  if (QRectF(mOuterRect).contains(pos))
32935  {
32936  if (mParentPlot)
32937  return mParentPlot->selectionTolerance()*0.99;
32938  else
32939  {
32940  qDebug() << Q_FUNC_INFO << "parent plot not defined";
32941  return -1;
32942  }
32943  } else
32944  return -1;
32945 }
32946 
32958 {
32959  QCPLayoutElement::update(phase);
32960 
32961  switch (phase)
32962  {
32963  case upPreparation:
32964  {
32965  setupTickVectors();
32966  for (int i=0; i<mRadialAxes.size(); ++i)
32967  mRadialAxes.at(i)->setupTickVectors();
32968  break;
32969  }
32970  case upLayout:
32971  {
32972  mCenter = mRect.center();
32973  mRadius = 0.5*qMin(qAbs(mRect.width()), qAbs(mRect.height()));
32974  if (mRadius < 1) mRadius = 1; // prevent cases where radius might become 0 which causes trouble
32975  for (int i=0; i<mRadialAxes.size(); ++i)
32976  mRadialAxes.at(i)->updateGeometry(mCenter, mRadius);
32977 
32979  break;
32980  }
32981  default: break;
32982  }
32983 
32984  // pass update call on to inset layout (doesn't happen automatically, because QCPPolarAxis doesn't derive from QCPLayout):
32985  mInsetLayout->update(phase);
32986 }
32987 
32988 /* inherits documentation from base class */
32989 QList<QCPLayoutElement*> QCPPolarAxisAngular::elements(bool recursive) const
32990 {
32991  QList<QCPLayoutElement*> result;
32992  if (mInsetLayout)
32993  {
32994  result << mInsetLayout;
32995  if (recursive)
32996  result << mInsetLayout->elements(recursive);
32997  }
32998  return result;
32999 }
33000 
33002 {
33003  if (!mGraphs.contains(graph))
33004  {
33005  qDebug() << Q_FUNC_INFO << "graph not in list:" << reinterpret_cast<quintptr>(graph);
33006  return false;
33007  }
33008 
33009  // remove plottable from legend:
33010  graph->removeFromLegend();
33011  // remove plottable:
33012  delete graph;
33013  mGraphs.removeOne(graph);
33014  return true;
33015 }
33016 
33017 /* inherits documentation from base class */
33019 {
33021 }
33022 
33023 /* inherits documentation from base class */
33025 {
33026  drawBackground(painter, mCenter, mRadius);
33027 
33028  // draw baseline circle:
33029  painter->setPen(getBasePen());
33030  painter->drawEllipse(mCenter, mRadius, mRadius);
33031 
33032  // draw subticks:
33033  if (!mSubTickVector.isEmpty())
33034  {
33035  painter->setPen(getSubTickPen());
33036  for (int i=0; i<mSubTickVector.size(); ++i)
33037  {
33040  }
33041  }
33042 
33043  // draw ticks and labels:
33044  if (!mTickVector.isEmpty())
33045  {
33049  const QPen ticksPen = getTickPen();
33050  painter->setPen(ticksPen);
33051  for (int i=0; i<mTickVector.size(); ++i)
33052  {
33053  const QPointF outerTick = mCenter+mTickVectorCosSin.at(i)*(mRadius+mTickLengthOut);
33054  painter->drawLine(mCenter+mTickVectorCosSin.at(i)*(mRadius-mTickLengthIn), outerTick);
33055  // draw tick labels:
33056  if (!mTickVectorLabels.isEmpty())
33057  {
33058  if (i < mTickVectorLabels.count()-1 || (mTickVectorCosSin.at(i)-mTickVectorCosSin.first()).manhattanLength() > 5/180.0*M_PI) // skip last label if it's closer than approx 5 degrees to first
33059  mLabelPainter.drawTickLabel(painter, outerTick, mTickVectorLabels.at(i));
33060  }
33061  }
33062  }
33063 }
33064 
33065 /* inherits documentation from base class */
33067 {
33068  return QCP::iSelectAxes;
33069 }
33070 
33071 
33087 void QCPPolarAxisAngular::setBackground(const QPixmap &pm)
33088 {
33089  mBackgroundPixmap = pm;
33090  mScaledBackgroundPixmap = QPixmap();
33091 }
33092 
33106 void QCPPolarAxisAngular::setBackground(const QBrush &brush)
33107 {
33108  mBackgroundBrush = brush;
33109 }
33110 
33118 void QCPPolarAxisAngular::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode)
33119 {
33120  mBackgroundPixmap = pm;
33121  mScaledBackgroundPixmap = QPixmap();
33122  mBackgroundScaled = scaled;
33123  mBackgroundScaledMode = mode;
33124 }
33125 
33137 {
33138  mBackgroundScaled = scaled;
33139 }
33140 
33146 void QCPPolarAxisAngular::setBackgroundScaledMode(Qt::AspectRatioMode mode)
33147 {
33148  mBackgroundScaledMode = mode;
33149 }
33150 
33152 {
33153  mRangeDrag = enabled;
33154 }
33155 
33157 {
33158  mRangeZoom = enabled;
33159 }
33160 
33162 {
33163  mRangeZoomFactor = factor;
33164 }
33165 
33166 
33167 
33168 
33169 
33170 
33171 
33181 {
33182  if (range.lower == mRange.lower && range.upper == mRange.upper)
33183  return;
33184 
33185  if (!QCPRange::validRange(range)) return;
33186  QCPRange oldRange = mRange;
33188  emit rangeChanged(mRange);
33189  emit rangeChanged(mRange, oldRange);
33190 }
33191 
33202 void QCPPolarAxisAngular::setSelectableParts(const SelectableParts &selectable)
33203 {
33204  if (mSelectableParts != selectable)
33205  {
33206  mSelectableParts = selectable;
33208  }
33209 }
33210 
33226 void QCPPolarAxisAngular::setSelectedParts(const SelectableParts &selected)
33227 {
33228  if (mSelectedParts != selected)
33229  {
33230  mSelectedParts = selected;
33232  }
33233 }
33234 
33244 void QCPPolarAxisAngular::setRange(double lower, double upper)
33245 {
33246  if (lower == mRange.lower && upper == mRange.upper)
33247  return;
33248 
33249  if (!QCPRange::validRange(lower, upper)) return;
33250  QCPRange oldRange = mRange;
33251  mRange.lower = lower;
33252  mRange.upper = upper;
33254  emit rangeChanged(mRange);
33255  emit rangeChanged(mRange, oldRange);
33256 }
33257 
33269 void QCPPolarAxisAngular::setRange(double position, double size, Qt::AlignmentFlag alignment)
33270 {
33271  if (alignment == Qt::AlignLeft)
33272  setRange(position, position+size);
33273  else if (alignment == Qt::AlignRight)
33274  setRange(position-size, position);
33275  else // alignment == Qt::AlignCenter
33276  setRange(position-size/2.0, position+size/2.0);
33277 }
33278 
33284 {
33285  if (mRange.lower == lower)
33286  return;
33287 
33288  QCPRange oldRange = mRange;
33289  mRange.lower = lower;
33291  emit rangeChanged(mRange);
33292  emit rangeChanged(mRange, oldRange);
33293 }
33294 
33300 {
33301  if (mRange.upper == upper)
33302  return;
33303 
33304  QCPRange oldRange = mRange;
33305  mRange.upper = upper;
33307  emit rangeChanged(mRange);
33308  emit rangeChanged(mRange, oldRange);
33309 }
33310 
33321 {
33322  mRangeReversed = reversed;
33323 }
33324 
33325 void QCPPolarAxisAngular::setAngle(double degrees)
33326 {
33327  mAngle = degrees;
33328  mAngleRad = mAngle/180.0*M_PI;
33329 }
33330 
33344 void QCPPolarAxisAngular::setTicker(QSharedPointer<QCPAxisTicker> ticker)
33345 {
33346  if (ticker)
33347  mTicker = ticker;
33348  else
33349  qDebug() << Q_FUNC_INFO << "can not set 0 as axis ticker";
33350  // no need to invalidate margin cache here because produced tick labels are checked for changes in setupTickVector
33351 }
33352 
33362 {
33363  if (mTicks != show)
33364  {
33365  mTicks = show;
33366  //mCachedMarginValid = false;
33367  }
33368 }
33369 
33374 {
33375  if (mTickLabels != show)
33376  {
33377  mTickLabels = show;
33378  //mCachedMarginValid = false;
33379  if (!mTickLabels)
33380  mTickVectorLabels.clear();
33381  }
33382 }
33383 
33389 {
33390  mLabelPainter.setPadding(padding);
33391 }
33392 
33399 {
33400  mTickLabelFont = font;
33401 }
33402 
33409 {
33411 }
33412 
33423 {
33424  mLabelPainter.setRotation(degrees);
33425 }
33426 
33428 {
33429  switch (mode)
33430  {
33433  }
33434 }
33435 
33466 void QCPPolarAxisAngular::setNumberFormat(const QString &formatCode)
33467 {
33468  if (formatCode.isEmpty())
33469  {
33470  qDebug() << Q_FUNC_INFO << "Passed formatCode is empty";
33471  return;
33472  }
33473  //mCachedMarginValid = false;
33474 
33475  // interpret first char as number format char:
33476  QString allowedFormatChars(QLatin1String("eEfgG"));
33477  if (allowedFormatChars.contains(formatCode.at(0)))
33478  {
33479  mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1());
33480  } else
33481  {
33482  qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode;
33483  return;
33484  }
33485 
33486  if (formatCode.length() < 2)
33487  {
33488  mNumberBeautifulPowers = false;
33489  mNumberMultiplyCross = false;
33490  } else
33491  {
33492  // interpret second char as indicator for beautiful decimal powers:
33493  if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g')))
33494  mNumberBeautifulPowers = true;
33495  else
33496  qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
33497 
33498  if (formatCode.length() < 3)
33499  {
33500  mNumberMultiplyCross = false;
33501  } else
33502  {
33503  // interpret third char as indicator for dot or cross multiplication symbol:
33504  if (formatCode.at(2) == QLatin1Char('c'))
33505  mNumberMultiplyCross = true;
33506  else if (formatCode.at(2) == QLatin1Char('d'))
33507  mNumberMultiplyCross = false;
33508  else
33509  qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
33510  }
33511  }
33514 }
33515 
33522 {
33523  if (mNumberPrecision != precision)
33524  {
33525  mNumberPrecision = precision;
33526  //mCachedMarginValid = false;
33527  }
33528 }
33529 
33538 void QCPPolarAxisAngular::setTickLength(int inside, int outside)
33539 {
33540  setTickLengthIn(inside);
33541  setTickLengthOut(outside);
33542 }
33543 
33551 {
33552  if (mTickLengthIn != inside)
33553  {
33554  mTickLengthIn = inside;
33555  }
33556 }
33557 
33566 {
33567  if (mTickLengthOut != outside)
33568  {
33569  mTickLengthOut = outside;
33570  //mCachedMarginValid = false; // only outside tick length can change margin
33571  }
33572 }
33573 
33582 {
33583  if (mSubTicks != show)
33584  {
33585  mSubTicks = show;
33586  //mCachedMarginValid = false;
33587  }
33588 }
33589 
33598 void QCPPolarAxisAngular::setSubTickLength(int inside, int outside)
33599 {
33600  setSubTickLengthIn(inside);
33601  setSubTickLengthOut(outside);
33602 }
33603 
33611 {
33612  if (mSubTickLengthIn != inside)
33613  {
33614  mSubTickLengthIn = inside;
33615  }
33616 }
33617 
33626 {
33627  if (mSubTickLengthOut != outside)
33628  {
33629  mSubTickLengthOut = outside;
33630  //mCachedMarginValid = false; // only outside tick length can change margin
33631  }
33632 }
33633 
33639 void QCPPolarAxisAngular::setBasePen(const QPen &pen)
33640 {
33641  mBasePen = pen;
33642 }
33643 
33649 void QCPPolarAxisAngular::setTickPen(const QPen &pen)
33650 {
33651  mTickPen = pen;
33652 }
33653 
33660 {
33661  mSubTickPen = pen;
33662 }
33663 
33669 void QCPPolarAxisAngular::setLabelFont(const QFont &font)
33670 {
33671  if (mLabelFont != font)
33672  {
33673  mLabelFont = font;
33674  //mCachedMarginValid = false;
33675  }
33676 }
33677 
33684 {
33685  mLabelColor = color;
33686 }
33687 
33692 void QCPPolarAxisAngular::setLabel(const QString &str)
33693 {
33694  if (mLabel != str)
33695  {
33696  mLabel = str;
33697  //mCachedMarginValid = false;
33698  }
33699 }
33700 
33707 {
33708  if (mLabelPadding != padding)
33709  {
33710  mLabelPadding = padding;
33711  //mCachedMarginValid = false;
33712  }
33713 }
33714 
33721 {
33722  if (font != mSelectedTickLabelFont)
33723  {
33724  mSelectedTickLabelFont = font;
33725  // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
33726  }
33727 }
33728 
33735 {
33736  mSelectedLabelFont = font;
33737  // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts
33738 }
33739 
33746 {
33748  {
33750  }
33751 }
33752 
33759 {
33761 }
33762 
33769 {
33770  mSelectedBasePen = pen;
33771 }
33772 
33779 {
33780  mSelectedTickPen = pen;
33781 }
33782 
33789 {
33790  mSelectedSubTickPen = pen;
33791 }
33792 
33811 void QCPPolarAxisAngular::drawBackground(QCPPainter *painter, const QPointF &center, double radius)
33812 {
33813  // draw background fill (don't use circular clip, looks bad):
33814  if (mBackgroundBrush != Qt::NoBrush)
33815  {
33816  QPainterPath ellipsePath;
33817  ellipsePath.addEllipse(center, radius, radius);
33818  painter->fillPath(ellipsePath, mBackgroundBrush);
33819  }
33820 
33821  // draw background pixmap (on top of fill, if brush specified):
33822  if (!mBackgroundPixmap.isNull())
33823  {
33824  QRegion clipCircle(center.x()-radius, center.y()-radius, qRound(2*radius), qRound(2*radius), QRegion::Ellipse);
33825  QRegion originalClip = painter->clipRegion();
33826  painter->setClipRegion(clipCircle);
33827  if (mBackgroundScaled)
33828  {
33829  // check whether mScaledBackground needs to be updated:
33830  QSize scaledSize(mBackgroundPixmap.size());
33831  scaledSize.scale(mRect.size(), mBackgroundScaledMode);
33832  if (mScaledBackgroundPixmap.size() != scaledSize)
33833  mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation);
33834  painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect());
33835  } else
33836  {
33837  painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()));
33838  }
33839  painter->setClipRegion(originalClip);
33840  }
33841 }
33842 
33852 {
33853  if (!mParentPlot) return;
33854  if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return;
33855 
33856  mSubTickVector.clear(); // since we might not pass it to mTicker->generate(), and we don't want old data in there
33858 
33859  // fill cos/sin buffers which will be used by draw() and QCPPolarGrid::draw(), so we don't have to calculate it twice:
33860  mTickVectorCosSin.resize(mTickVector.size());
33861  for (int i=0; i<mTickVector.size(); ++i)
33862  {
33863  const double theta = coordToAngleRad(mTickVector.at(i));
33864  mTickVectorCosSin[i] = QPointF(qCos(theta), qSin(theta));
33865  }
33866  mSubTickVectorCosSin.resize(mSubTickVector.size());
33867  for (int i=0; i<mSubTickVector.size(); ++i)
33868  {
33869  const double theta = coordToAngleRad(mSubTickVector.at(i));
33870  mSubTickVectorCosSin[i] = QPointF(qCos(theta), qSin(theta));
33871  }
33872 }
33873 
33880 {
33881  return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen;
33882 }
33883 
33890 {
33891  return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen;
33892 }
33893 
33900 {
33902 }
33903 
33910 {
33912 }
33913 
33920 {
33922 }
33923 
33930 {
33932 }
33933 
33940 {
33942 }
33943 
33955 void QCPPolarAxisAngular::mousePressEvent(QMouseEvent *event, const QVariant &details)
33956 {
33957  Q_UNUSED(details)
33958  if (event->buttons() & Qt::LeftButton)
33959  {
33960  mDragging = true;
33961  // initialize antialiasing backup in case we start dragging:
33963  {
33966  }
33967  // Mouse range dragging interaction:
33968  if (mParentPlot->interactions().testFlag(QCP::iRangeDrag))
33969  {
33971  mDragRadialStart.clear();
33972  for (int i=0; i<mRadialAxes.size(); ++i)
33973  mDragRadialStart.append(mRadialAxes.at(i)->range());
33974  }
33975  }
33976 }
33977 
33985 void QCPPolarAxisAngular::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
33986 {
33987  Q_UNUSED(startPos)
33988  bool doReplot = false;
33989  // Mouse range dragging interaction:
33990  if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag))
33991  {
33992  if (mRangeDrag)
33993  {
33994  doReplot = true;
33995  double angleCoordStart, radiusCoordStart;
33996  double angleCoord, radiusCoord;
33997  pixelToCoord(startPos, angleCoordStart, radiusCoordStart);
33998  pixelToCoord(event->pos(), angleCoord, radiusCoord);
33999  double diff = angleCoordStart - angleCoord;
34001  }
34002 
34003  for (int i=0; i<mRadialAxes.size(); ++i)
34004  {
34005  QCPPolarAxisRadial *ax = mRadialAxes.at(i);
34006  if (!ax->rangeDrag())
34007  continue;
34008  doReplot = true;
34009  double angleCoordStart, radiusCoordStart;
34010  double angleCoord, radiusCoord;
34011  ax->pixelToCoord(startPos, angleCoordStart, radiusCoordStart);
34012  ax->pixelToCoord(event->pos(), angleCoord, radiusCoord);
34014  {
34015  double diff = radiusCoordStart - radiusCoord;
34016  ax->setRange(mDragRadialStart.at(i).lower+diff, mDragRadialStart.at(i).upper+diff);
34017  } else if (ax->scaleType() == QCPPolarAxisRadial::stLogarithmic)
34018  {
34019  if (radiusCoord != 0)
34020  {
34021  double diff = radiusCoordStart/radiusCoord;
34022  ax->setRange(mDragRadialStart.at(i).lower*diff, mDragRadialStart.at(i).upper*diff);
34023  }
34024  }
34025  }
34026 
34027  if (doReplot) // if either vertical or horizontal drag was enabled, do a replot
34028  {
34032  }
34033  }
34034 }
34035 
34036 /* inherits documentation from base class */
34037 void QCPPolarAxisAngular::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
34038 {
34039  Q_UNUSED(event)
34040  Q_UNUSED(startPos)
34041  mDragging = false;
34043  {
34046  }
34047 }
34048 
34063 void QCPPolarAxisAngular::wheelEvent(QWheelEvent *event)
34064 {
34065  bool doReplot = false;
34066  // Mouse range zooming interaction:
34067  if (mParentPlot->interactions().testFlag(QCP::iRangeZoom))
34068  {
34069 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
34070  const double delta = event->delta();
34071 #else
34072  const double delta = event->angleDelta().y();
34073 #endif
34074 
34075 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
34076  const QPointF pos = event->pos();
34077 #else
34078  const QPointF pos = event->position();
34079 #endif
34080  const double wheelSteps = delta/120.0; // a single step delta is +/-120 usually
34081  if (mRangeZoom)
34082  {
34083  double angleCoord, radiusCoord;
34084  pixelToCoord(pos, angleCoord, radiusCoord);
34085  scaleRange(qPow(mRangeZoomFactor, wheelSteps), angleCoord);
34086  }
34087 
34088  for (int i=0; i<mRadialAxes.size(); ++i)
34089  {
34090  QCPPolarAxisRadial *ax = mRadialAxes.at(i);
34091  if (!ax->rangeZoom())
34092  continue;
34093  doReplot = true;
34094  double angleCoord, radiusCoord;
34095  ax->pixelToCoord(pos, angleCoord, radiusCoord);
34096  ax->scaleRange(qPow(ax->rangeZoomFactor(), wheelSteps), radiusCoord);
34097  }
34098  }
34099  if (doReplot)
34100  mParentPlot->replot();
34101 }
34102 
34104 {
34105  if (mGraphs.contains(graph))
34106  {
34107  qDebug() << Q_FUNC_INFO << "plottable already added:" << reinterpret_cast<quintptr>(graph);
34108  return false;
34109  }
34110  if (graph->keyAxis() != this)
34111  {
34112  qDebug() << Q_FUNC_INFO << "plottable not created with this as axis:" << reinterpret_cast<quintptr>(graph);
34113  return false;
34114  }
34115 
34116  mGraphs.append(graph);
34117  // possibly add plottable to legend:
34119  graph->addToLegend();
34120  if (!graph->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor)
34121  graph->setLayer(mParentPlot->currentLayer());
34122  return true;
34123 }
34124 /* end of 'src/polar/layoutelement-angularaxis.cpp' */
34125 
34126 
34127 /* including file 'src/polar/polargrid.cpp' */
34128 /* modified 2021-03-29T02:30:44, size 7493 */
34129 
34130 
34134 
34148  QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
34149  mType(gtNone),
34150  mSubGridType(gtNone),
34151  mAntialiasedSubGrid(true),
34152  mAntialiasedZeroLine(true),
34153  mParentAxis(parentAxis)
34154 {
34155  // warning: this is called in QCPPolarAxisAngular constructor, so parentAxis members should not be accessed/called
34156  setParent(parentAxis);
34157  setType(gtAll);
34159 
34160  setAngularPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
34161  setAngularSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
34162 
34163  setRadialPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
34164  setRadialSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
34165  setRadialZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine));
34166 
34167  setAntialiased(true);
34168 }
34169 
34171 {
34172  mRadialAxis = axis;
34173 }
34174 
34175 void QCPPolarGrid::setType(GridTypes type)
34176 {
34177  mType = type;
34178 }
34179 
34180 void QCPPolarGrid::setSubGridType(GridTypes type)
34181 {
34182  mSubGridType = type;
34183 }
34184 
34189 {
34190  mAntialiasedSubGrid = enabled;
34191 }
34192 
34197 {
34198  mAntialiasedZeroLine = enabled;
34199 }
34200 
34204 void QCPPolarGrid::setAngularPen(const QPen &pen)
34205 {
34206  mAngularPen = pen;
34207 }
34208 
34213 {
34214  mAngularSubGridPen = pen;
34215 }
34216 
34217 void QCPPolarGrid::setRadialPen(const QPen &pen)
34218 {
34219  mRadialPen = pen;
34220 }
34221 
34223 {
34224  mRadialSubGridPen = pen;
34225 }
34226 
34228 {
34229  mRadialZeroLinePen = pen;
34230 }
34231 
34246 {
34248 }
34249 
34256 {
34257  if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; }
34258 
34259  const QPointF center = mParentAxis->mCenter;
34260  const double radius = mParentAxis->mRadius;
34261 
34262  painter->setBrush(Qt::NoBrush);
34263  // draw main angular grid:
34264  if (mType.testFlag(gtAngular))
34265  drawAngularGrid(painter, center, radius, mParentAxis->mTickVectorCosSin, mAngularPen);
34266  // draw main radial grid:
34267  if (mType.testFlag(gtRadial) && mRadialAxis)
34268  drawRadialGrid(painter, center, mRadialAxis->tickVector(), mRadialPen, mRadialZeroLinePen);
34269 
34271  // draw sub angular grid:
34272  if (mSubGridType.testFlag(gtAngular))
34274  // draw sub radial grid:
34275  if (mSubGridType.testFlag(gtRadial) && mRadialAxis)
34276  drawRadialGrid(painter, center, mRadialAxis->subTickVector(), mRadialSubGridPen);
34277 }
34278 
34279 void QCPPolarGrid::drawRadialGrid(QCPPainter *painter, const QPointF &center, const QVector<double> &coords, const QPen &pen, const QPen &zeroPen)
34280 {
34281  if (!mRadialAxis) return;
34282  if (coords.isEmpty()) return;
34283  const bool drawZeroLine = zeroPen != Qt::NoPen;
34284  const double zeroLineEpsilon = qAbs(coords.last()-coords.first())*1e-6;
34285 
34286  painter->setPen(pen);
34287  for (int i=0; i<coords.size(); ++i)
34288  {
34289  const double r = mRadialAxis->coordToRadius(coords.at(i));
34290  if (drawZeroLine && qAbs(coords.at(i)) < zeroLineEpsilon)
34291  {
34293  painter->setPen(zeroPen);
34294  painter->drawEllipse(center, r, r);
34295  painter->setPen(pen);
34297  } else
34298  {
34299  painter->drawEllipse(center, r, r);
34300  }
34301  }
34302 }
34303 
34304 void QCPPolarGrid::drawAngularGrid(QCPPainter *painter, const QPointF &center, double radius, const QVector<QPointF> &ticksCosSin, const QPen &pen)
34305 {
34306  if (ticksCosSin.isEmpty()) return;
34307 
34308  painter->setPen(pen);
34309  for (int i=0; i<ticksCosSin.size(); ++i)
34310  painter->drawLine(center, center+ticksCosSin.at(i)*radius);
34311 }
34312 /* end of 'src/polar/polargrid.cpp' */
34313 
34314 
34315 /* including file 'src/polar/polargraph.cpp' */
34316 /* modified 2021-03-29T02:30:44, size 44035 */
34317 
34318 
34322 
34330  QCPAbstractLegendItem(parent),
34331  mPolarGraph(graph)
34332 {
34333  setAntialiased(false);
34334 }
34335 
34337 {
34338  if (!mPolarGraph) return;
34339  painter->setFont(getFont());
34340  painter->setPen(QPen(getTextColor()));
34341  QSizeF iconSize = mParentLegend->iconSize();
34342  QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPolarGraph->name());
34343  QRectF iconRect(mRect.topLeft(), iconSize);
34344  int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops
34345  painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPolarGraph->name());
34346  // draw icon:
34347  painter->save();
34348  painter->setClipRect(iconRect, Qt::IntersectClip);
34349  mPolarGraph->drawLegendIcon(painter, iconRect);
34350  painter->restore();
34351  // draw icon border:
34352  if (getIconBorderPen().style() != Qt::NoPen)
34353  {
34354  painter->setPen(getIconBorderPen());
34355  painter->setBrush(Qt::NoBrush);
34356  int halfPen = qCeil(painter->pen().widthF()*0.5)+1;
34357  painter->setClipRect(mOuterRect.adjusted(-halfPen, -halfPen, halfPen, halfPen)); // extend default clip rect so thicker pens (especially during selection) are not clipped
34358  painter->drawRect(iconRect);
34359  }
34360 }
34361 
34363 {
34364  if (!mPolarGraph) return QSize();
34365  QSize result(0, 0);
34366  QRect textRect;
34367  QFontMetrics fontMetrics(getFont());
34368  QSize iconSize = mParentLegend->iconSize();
34369  textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPolarGraph->name());
34370  result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width());
34371  result.setHeight(qMax(textRect.height(), iconSize.height()));
34372  result.rwidth() += mMargins.left()+mMargins.right();
34373  result.rheight() += mMargins.top()+mMargins.bottom();
34374  return result;
34375 }
34376 
34378 {
34380 }
34381 
34383 {
34385 }
34386 
34388 {
34389  return mSelected ? mSelectedFont : mFont;
34390 }
34391 
34392 
34396 
34404 /* start of documentation of inline functions */
34405 
34406 // TODO
34407 
34408 /* end of documentation of inline functions */
34409 
34424  QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis),
34425  mDataContainer(new QCPGraphDataContainer),
34426  mName(),
34427  mAntialiasedFill(true),
34428  mAntialiasedScatters(true),
34429  mPen(Qt::black),
34430  mBrush(Qt::NoBrush),
34431  mPeriodic(true),
34432  mKeyAxis(keyAxis),
34433  mValueAxis(valueAxis),
34434  mSelectable(QCP::stWhole)
34435  //mSelectionDecorator(0) // TODO
34436 {
34437  if (keyAxis->parentPlot() != valueAxis->parentPlot())
34438  qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis.";
34439 
34440  mKeyAxis->registerPolarGraph(this);
34441 
34442  //setSelectionDecorator(new QCPSelectionDecorator); // TODO
34443 
34444  setPen(QPen(Qt::blue, 0));
34445  setBrush(Qt::NoBrush);
34447 }
34448 
34450 {
34451  /* TODO
34452  if (mSelectionDecorator)
34453  {
34454  delete mSelectionDecorator;
34455  mSelectionDecorator = 0;
34456  }
34457  */
34458 }
34459 
34464 void QCPPolarGraph::setName(const QString &name)
34465 {
34466  mName = name;
34467 }
34468 
34476 {
34477  mAntialiasedFill = enabled;
34478 }
34479 
34487 {
34488  mAntialiasedScatters = enabled;
34489 }
34490 
34499 void QCPPolarGraph::setPen(const QPen &pen)
34500 {
34501  mPen = pen;
34502 }
34503 
34513 void QCPPolarGraph::setBrush(const QBrush &brush)
34514 {
34515  mBrush = brush;
34516 }
34517 
34518 void QCPPolarGraph::setPeriodic(bool enabled)
34519 {
34520  mPeriodic = enabled;
34521 }
34522 
34535 {
34536  mKeyAxis = axis;
34537 }
34538 
34551 {
34552  mValueAxis = axis;
34553 }
34554 
34566 {
34567  if (mSelectable != selectable)
34568  {
34570  QCPDataSelection oldSelection = mSelection;
34573  if (mSelection != oldSelection)
34574  {
34575  emit selectionChanged(selected());
34577  }
34578  }
34579 }
34580 
34600 {
34602  if (mSelection != selection)
34603  {
34605  emit selectionChanged(selected());
34607  }
34608 }
34609 
34625 void QCPPolarGraph::setData(QSharedPointer<QCPGraphDataContainer> data)
34626 {
34627  mDataContainer = data;
34628 }
34629 
34641 void QCPPolarGraph::setData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
34642 {
34643  mDataContainer->clear();
34644  addData(keys, values, alreadySorted);
34645 }
34646 
34654 {
34655  mLineStyle = ls;
34656 }
34657 
34665 {
34666  mScatterStyle = style;
34667 }
34668 
34669 void QCPPolarGraph::addData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
34670 {
34671  if (keys.size() != values.size())
34672  qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size();
34673  const int n = qMin(keys.size(), values.size());
34674  QVector<QCPGraphData> tempData(n);
34675  QVector<QCPGraphData>::iterator it = tempData.begin();
34676  const QVector<QCPGraphData>::iterator itEnd = tempData.end();
34677  int i = 0;
34678  while (it != itEnd)
34679  {
34680  it->key = keys[i];
34681  it->value = values[i];
34682  ++it;
34683  ++i;
34684  }
34685  mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write
34686 }
34687 
34688 void QCPPolarGraph::addData(double key, double value)
34689 {
34690  mDataContainer->add(QCPGraphData(key, value));
34691 }
34692 
34702 /*
34703 void QCPPolarGraph::setSelectionDecorator(QCPSelectionDecorator *decorator)
34704 {
34705  if (decorator)
34706  {
34707  if (decorator->registerWithPlottable(this))
34708  {
34709  if (mSelectionDecorator) // delete old decorator if necessary
34710  delete mSelectionDecorator;
34711  mSelectionDecorator = decorator;
34712  }
34713  } else if (mSelectionDecorator) // just clear decorator
34714  {
34715  delete mSelectionDecorator;
34716  mSelectionDecorator = 0;
34717  }
34718 }
34719 */
34720 
34721 void QCPPolarGraph::coordsToPixels(double key, double value, double &x, double &y) const
34722 {
34723  if (mValueAxis)
34724  {
34725  const QPointF point = mValueAxis->coordToPixel(key, value);
34726  x = point.x();
34727  y = point.y();
34728  } else
34729  {
34730  qDebug() << Q_FUNC_INFO << "invalid key or value axis";
34731  }
34732 }
34733 
34734 const QPointF QCPPolarGraph::coordsToPixels(double key, double value) const
34735 {
34736  if (mValueAxis)
34737  {
34738  return mValueAxis->coordToPixel(key, value);
34739  } else
34740  {
34741  qDebug() << Q_FUNC_INFO << "invalid key or value axis";
34742  return QPointF();
34743  }
34744 }
34745 
34746 void QCPPolarGraph::pixelsToCoords(double x, double y, double &key, double &value) const
34747 {
34748  if (mValueAxis)
34749  {
34750  mValueAxis->pixelToCoord(QPointF(x, y), key, value);
34751  } else
34752  {
34753  qDebug() << Q_FUNC_INFO << "invalid key or value axis";
34754  }
34755 }
34756 
34757 void QCPPolarGraph::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const
34758 {
34759  if (mValueAxis)
34760  {
34761  mValueAxis->pixelToCoord(pixelPos, key, value);
34762  } else
34763  {
34764  qDebug() << Q_FUNC_INFO << "invalid key or value axis";
34765  }
34766 }
34767 
34768 void QCPPolarGraph::rescaleAxes(bool onlyEnlarge) const
34769 {
34770  rescaleKeyAxis(onlyEnlarge);
34771  rescaleValueAxis(onlyEnlarge);
34772 }
34773 
34774 void QCPPolarGraph::rescaleKeyAxis(bool onlyEnlarge) const
34775 {
34777  if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; }
34778 
34779  bool foundRange;
34780  QCPRange newRange = getKeyRange(foundRange, QCP::sdBoth);
34781  if (foundRange)
34782  {
34783  if (onlyEnlarge)
34784  newRange.expand(keyAxis->range());
34785  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
34786  {
34787  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
34788  newRange.lower = center-keyAxis->range().size()/2.0;
34789  newRange.upper = center+keyAxis->range().size()/2.0;
34790  }
34791  keyAxis->setRange(newRange);
34792  }
34793 }
34794 
34795 void QCPPolarGraph::rescaleValueAxis(bool onlyEnlarge, bool inKeyRange) const
34796 {
34799  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
34800 
34801  QCP::SignDomain signDomain = QCP::sdBoth;
34803  signDomain = (valueAxis->range().upper < 0 ? QCP::sdNegative : QCP::sdPositive);
34804 
34805  bool foundRange;
34806  QCPRange newRange = getValueRange(foundRange, signDomain, inKeyRange ? keyAxis->range() : QCPRange());
34807  if (foundRange)
34808  {
34809  if (onlyEnlarge)
34810  newRange.expand(valueAxis->range());
34811  if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable
34812  {
34813  double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason
34815  {
34816  newRange.lower = center-valueAxis->range().size()/2.0;
34817  newRange.upper = center+valueAxis->range().size()/2.0;
34818  } else // scaleType() == stLogarithmic
34819  {
34820  newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower);
34821  newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower);
34822  }
34823  }
34824  valueAxis->setRange(newRange);
34825  }
34826 }
34827 
34829 {
34830  if (!legend)
34831  {
34832  qDebug() << Q_FUNC_INFO << "passed legend is null";
34833  return false;
34834  }
34835  if (legend->parentPlot() != mParentPlot)
34836  {
34837  qDebug() << Q_FUNC_INFO << "passed legend isn't in the same QCustomPlot as this plottable";
34838  return false;
34839  }
34840 
34841  //if (!legend->hasItemWithPlottable(this)) // TODO
34842  //{
34843  legend->addItem(new QCPPolarLegendItem(legend, this));
34844  return true;
34845  //} else
34846  // return false;
34847 }
34848 
34850 {
34851  if (!mParentPlot || !mParentPlot->legend)
34852  return false;
34853  else
34854  return addToLegend(mParentPlot->legend);
34855 }
34856 
34858 {
34859  if (!legend)
34860  {
34861  qDebug() << Q_FUNC_INFO << "passed legend is null";
34862  return false;
34863  }
34864 
34865 
34866  QCPPolarLegendItem *removableItem = 0;
34867  for (int i=0; i<legend->itemCount(); ++i) // TODO: reduce this to code in QCPAbstractPlottable::removeFromLegend once unified
34868  {
34869  if (QCPPolarLegendItem *pli = qobject_cast<QCPPolarLegendItem*>(legend->item(i)))
34870  {
34871  if (pli->polarGraph() == this)
34872  {
34873  removableItem = pli;
34874  break;
34875  }
34876  }
34877  }
34878 
34879  if (removableItem)
34880  return legend->removeItem(removableItem);
34881  else
34882  return false;
34883 }
34884 
34886 {
34887  if (!mParentPlot || !mParentPlot->legend)
34888  return false;
34889  else
34891 }
34892 
34893 double QCPPolarGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
34894 {
34895  if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
34896  return -1;
34897  if (!mKeyAxis || !mValueAxis)
34898  return -1;
34899 
34900  if (mKeyAxis->rect().contains(pos.toPoint()))
34901  {
34902  QCPGraphDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd();
34903  double result = pointDistance(pos, closestDataPoint);
34904  if (details)
34905  {
34906  int pointIndex = closestDataPoint-mDataContainer->constBegin();
34907  details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1)));
34908  }
34909  return result;
34910  } else
34911  return -1;
34912 }
34913 
34914 /* inherits documentation from base class */
34915 QCPRange QCPPolarGraph::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const
34916 {
34917  return mDataContainer->keyRange(foundRange, inSignDomain);
34918 }
34919 
34920 /* inherits documentation from base class */
34921 QCPRange QCPPolarGraph::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const
34922 {
34923  return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
34924 }
34925 
34926 /* inherits documentation from base class */
34928 {
34929  if (mKeyAxis)
34930  return mKeyAxis.data()->rect();
34931  else
34932  return QRect();
34933 }
34934 
34936 {
34937  if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
34938  if (mKeyAxis.data()->range().size() <= 0 || mDataContainer->isEmpty()) return;
34939  if (mLineStyle == lsNone && mScatterStyle.isNone()) return;
34940 
34941  painter->setClipRegion(mKeyAxis->exactClipRegion());
34942 
34943  QVector<QPointF> lines, scatters; // line and (if necessary) scatter pixel coordinates will be stored here while iterating over segments
34944 
34945  // loop over and draw segments of unselected/selected data:
34946  QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
34947  getDataSegments(selectedSegments, unselectedSegments);
34948  allSegments << unselectedSegments << selectedSegments;
34949  for (int i=0; i<allSegments.size(); ++i)
34950  {
34951  bool isSelectedSegment = i >= unselectedSegments.size();
34952  // get line pixel points appropriate to line style:
34953  QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).adjusted(-1, 1); // unselected segments extend lines to bordering selected data point (safe to exceed total data bounds in first/last segment, getLines takes care)
34954  getLines(&lines, lineDataRange);
34955 
34956  // check data validity if flag set:
34957 #ifdef QCUSTOMPLOT_CHECK_DATA
34959  for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it)
34960  {
34961  if (QCP::isInvalidData(it->key, it->value))
34962  qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "invalid." << "Plottable name:" << name();
34963  }
34964 #endif
34965 
34966  // draw fill of graph:
34967  //if (isSelectedSegment && mSelectionDecorator)
34968  // mSelectionDecorator->applyBrush(painter);
34969  //else
34970  painter->setBrush(mBrush);
34971  painter->setPen(Qt::NoPen);
34972  drawFill(painter, &lines);
34973 
34974 
34975  // draw line:
34976  if (mLineStyle != lsNone)
34977  {
34978  //if (isSelectedSegment && mSelectionDecorator)
34979  // mSelectionDecorator->applyPen(painter);
34980  //else
34981  painter->setPen(mPen);
34982  painter->setBrush(Qt::NoBrush);
34983  drawLinePlot(painter, lines);
34984  }
34985 
34986  // draw scatters:
34987 
34988  QCPScatterStyle finalScatterStyle = mScatterStyle;
34989  //if (isSelectedSegment && mSelectionDecorator)
34990  // finalScatterStyle = mSelectionDecorator->getFinalScatterStyle(mScatterStyle);
34991  if (!finalScatterStyle.isNone())
34992  {
34993  getScatters(&scatters, allSegments.at(i));
34994  drawScatterPlot(painter, scatters, finalScatterStyle);
34995  }
34996  }
34997 
34998  // draw other selection decoration that isn't just line/scatter pens and brushes:
34999  //if (mSelectionDecorator)
35000  // mSelectionDecorator->drawDecoration(painter, selection());
35001 }
35002 
35004 {
35005  return QCP::iSelectPlottables;
35006 }
35007 
35009 {
35011 }
35012 
35013 /* inherits documentation from base class */
35014 void QCPPolarGraph::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
35015 {
35016  Q_UNUSED(event)
35017 
35018  if (mSelectable != QCP::stNone)
35019  {
35020  QCPDataSelection newSelection = details.value<QCPDataSelection>();
35021  QCPDataSelection selectionBefore = mSelection;
35022  if (additive)
35023  {
35024  if (mSelectable == QCP::stWhole) // in whole selection mode, we toggle to no selection even if currently unselected point was hit
35025  {
35026  if (selected())
35028  else
35029  setSelection(newSelection);
35030  } else // in all other selection modes we toggle selections of homogeneously selected/unselected segments
35031  {
35032  if (mSelection.contains(newSelection)) // if entire newSelection is already selected, toggle selection
35033  setSelection(mSelection-newSelection);
35034  else
35035  setSelection(mSelection+newSelection);
35036  }
35037  } else
35038  setSelection(newSelection);
35039  if (selectionStateChanged)
35040  *selectionStateChanged = mSelection != selectionBefore;
35041  }
35042 }
35043 
35044 /* inherits documentation from base class */
35045 void QCPPolarGraph::deselectEvent(bool *selectionStateChanged)
35046 {
35047  if (mSelectable != QCP::stNone)
35048  {
35049  QCPDataSelection selectionBefore = mSelection;
35051  if (selectionStateChanged)
35052  *selectionStateChanged = mSelection != selectionBefore;
35053  }
35054 }
35055 
35062 void QCPPolarGraph::drawLinePlot(QCPPainter *painter, const QVector<QPointF> &lines) const
35063 {
35064  if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
35065  {
35067  drawPolyline(painter, lines);
35068  }
35069 }
35070 
35088 void QCPPolarGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lines) const
35089 {
35090  applyFillAntialiasingHint(painter);
35091  if (painter->brush().style() != Qt::NoBrush && painter->brush().color().alpha() != 0)
35092  painter->drawPolygon(QPolygonF(*lines));
35093 }
35094 
35102 void QCPPolarGraph::drawScatterPlot(QCPPainter *painter, const QVector<QPointF> &scatters, const QCPScatterStyle &style) const
35103 {
35105  style.applyTo(painter, mPen);
35106  for (int i=0; i<scatters.size(); ++i)
35107  style.drawShape(painter, scatters.at(i).x(), scatters.at(i).y());
35108 }
35109 
35110 void QCPPolarGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
35111 {
35112  // draw fill:
35113  if (mBrush.style() != Qt::NoBrush)
35114  {
35115  applyFillAntialiasingHint(painter);
35116  painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush);
35117  }
35118  // draw line vertically centered:
35119  if (mLineStyle != lsNone)
35120  {
35122  painter->setPen(mPen);
35123  painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens
35124  }
35125  // draw scatter symbol:
35126  if (!mScatterStyle.isNone())
35127  {
35129  // scale scatter pixmap if it's too large to fit in legend icon rect:
35130  if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height()))
35131  {
35132  QCPScatterStyle scaledStyle(mScatterStyle);
35133  scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
35134  scaledStyle.applyTo(painter, mPen);
35135  scaledStyle.drawShape(painter, QRectF(rect).center());
35136  } else
35137  {
35138  mScatterStyle.applyTo(painter, mPen);
35139  mScatterStyle.drawShape(painter, QRectF(rect).center());
35140  }
35141  }
35142 }
35143 
35145 {
35147 }
35148 
35150 {
35152 }
35153 
35154 double QCPPolarGraph::pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const
35155 {
35156  closestData = mDataContainer->constEnd();
35157  if (mDataContainer->isEmpty())
35158  return -1.0;
35159  if (mLineStyle == lsNone && mScatterStyle.isNone())
35160  return -1.0;
35161 
35162  // calculate minimum distances to graph data points and find closestData iterator:
35163  double minDistSqr = (std::numeric_limits<double>::max)();
35164  // determine which key range comes into question, taking selection tolerance around pos into account:
35165  double posKeyMin, posKeyMax, dummy;
35166  pixelsToCoords(pixelPoint-QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMin, dummy);
35167  pixelsToCoords(pixelPoint+QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMax, dummy);
35168  if (posKeyMin > posKeyMax)
35169  qSwap(posKeyMin, posKeyMax);
35170  // iterate over found data points and then choose the one with the shortest distance to pos:
35171  QCPGraphDataContainer::const_iterator begin = mDataContainer->findBegin(posKeyMin, true);
35172  QCPGraphDataContainer::const_iterator end = mDataContainer->findEnd(posKeyMax, true);
35173  for (QCPGraphDataContainer::const_iterator it=begin; it!=end; ++it)
35174  {
35175  const double currentDistSqr = QCPVector2D(coordsToPixels(it->key, it->value)-pixelPoint).lengthSquared();
35176  if (currentDistSqr < minDistSqr)
35177  {
35178  minDistSqr = currentDistSqr;
35179  closestData = it;
35180  }
35181  }
35182 
35183  // calculate distance to graph line if there is one (if so, will probably be smaller than distance to closest data point):
35184  if (mLineStyle != lsNone)
35185  {
35186  // line displayed, calculate distance to line segments:
35187  QVector<QPointF> lineData;
35188  getLines(&lineData, QCPDataRange(0, dataCount()));
35189  QCPVector2D p(pixelPoint);
35190  for (int i=0; i<lineData.size()-1; ++i)
35191  {
35192  const double currentDistSqr = p.distanceSquaredToLine(lineData.at(i), lineData.at(i+1));
35193  if (currentDistSqr < minDistSqr)
35194  minDistSqr = currentDistSqr;
35195  }
35196  }
35197 
35198  return qSqrt(minDistSqr);
35199 }
35200 
35202 {
35203  return mDataContainer->size();
35204 }
35205 
35206 void QCPPolarGraph::getDataSegments(QList<QCPDataRange> &selectedSegments, QList<QCPDataRange> &unselectedSegments) const
35207 {
35208  selectedSegments.clear();
35209  unselectedSegments.clear();
35210  if (mSelectable == QCP::stWhole) // stWhole selection type draws the entire plottable with selected style if mSelection isn't empty
35211  {
35212  if (selected())
35213  selectedSegments << QCPDataRange(0, dataCount());
35214  else
35215  unselectedSegments << QCPDataRange(0, dataCount());
35216  } else
35217  {
35218  QCPDataSelection sel(selection());
35219  sel.simplify();
35220  selectedSegments = sel.dataRanges();
35221  unselectedSegments = sel.inverse(QCPDataRange(0, dataCount())).dataRanges();
35222  }
35223 }
35224 
35225 void QCPPolarGraph::drawPolyline(QCPPainter *painter, const QVector<QPointF> &lineData) const
35226 {
35227  // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
35228  if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
35229  painter->pen().style() == Qt::SolidLine &&
35230  !painter->modes().testFlag(QCPPainter::pmVectorized) &&
35231  !painter->modes().testFlag(QCPPainter::pmNoCaching))
35232  {
35233  int i = 0;
35234  bool lastIsNan = false;
35235  const int lineDataSize = lineData.size();
35236  while (i < lineDataSize && (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()))) // make sure first point is not NaN
35237  ++i;
35238  ++i; // because drawing works in 1 point retrospect
35239  while (i < lineDataSize)
35240  {
35241  if (!qIsNaN(lineData.at(i).y()) && !qIsNaN(lineData.at(i).x())) // NaNs create a gap in the line
35242  {
35243  if (!lastIsNan)
35244  painter->drawLine(lineData.at(i-1), lineData.at(i));
35245  else
35246  lastIsNan = false;
35247  } else
35248  lastIsNan = true;
35249  ++i;
35250  }
35251  } else
35252  {
35253  int segmentStart = 0;
35254  int i = 0;
35255  const int lineDataSize = lineData.size();
35256  while (i < lineDataSize)
35257  {
35258  if (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()) || qIsInf(lineData.at(i).y())) // NaNs create a gap in the line. Also filter Infs which make drawPolyline block
35259  {
35260  painter->drawPolyline(lineData.constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
35261  segmentStart = i+1;
35262  }
35263  ++i;
35264  }
35265  // draw last segment:
35266  painter->drawPolyline(lineData.constData()+segmentStart, lineDataSize-segmentStart);
35267  }
35268 }
35269 
35271 {
35272  if (rangeRestriction.isEmpty())
35273  {
35274  end = mDataContainer->constEnd();
35275  begin = end;
35276  } else
35277  {
35280  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
35281  // get visible data range:
35282  if (mPeriodic)
35283  {
35284  begin = mDataContainer->constBegin();
35285  end = mDataContainer->constEnd();
35286  } else
35287  {
35288  begin = mDataContainer->findBegin(keyAxis->range().lower);
35289  end = mDataContainer->findEnd(keyAxis->range().upper);
35290  }
35291  // limit lower/upperEnd to rangeRestriction:
35292  mDataContainer->limitIteratorsToDataRange(begin, end, rangeRestriction); // this also ensures rangeRestriction outside data bounds doesn't break anything
35293  }
35294 }
35295 
35316 void QCPPolarGraph::getLines(QVector<QPointF> *lines, const QCPDataRange &dataRange) const
35317 {
35318  if (!lines) return;
35320  getVisibleDataBounds(begin, end, dataRange);
35321  if (begin == end)
35322  {
35323  lines->clear();
35324  return;
35325  }
35326 
35327  QVector<QCPGraphData> lineData;
35328  if (mLineStyle != lsNone)
35329  getOptimizedLineData(&lineData, begin, end);
35330 
35331  switch (mLineStyle)
35332  {
35333  case lsNone: lines->clear(); break;
35334  case lsLine: *lines = dataToLines(lineData); break;
35335  }
35336 }
35337 
35338 void QCPPolarGraph::getScatters(QVector<QPointF> *scatters, const QCPDataRange &dataRange) const
35339 {
35342  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
35343 
35344  if (!scatters) return;
35346  getVisibleDataBounds(begin, end, dataRange);
35347  if (begin == end)
35348  {
35349  scatters->clear();
35350  return;
35351  }
35352 
35353  QVector<QCPGraphData> data;
35354  getOptimizedScatterData(&data, begin, end);
35355 
35356  scatters->resize(data.size());
35357  for (int i=0; i<data.size(); ++i)
35358  {
35359  if (!qIsNaN(data.at(i).value))
35360  (*scatters)[i] = valueAxis->coordToPixel(data.at(i).key, data.at(i).value);
35361  }
35362 }
35363 
35365 {
35366  lineData->clear();
35367 
35368  // TODO: fix for log axes and thick line style
35369 
35370  const QCPRange range = mValueAxis->range();
35371  bool reversed = mValueAxis->rangeReversed();
35372  const double clipMargin = range.size()*0.05; // extra distance from visible circle, so optimized outside lines can cover more angle before having to place a dummy point to prevent tangents
35373  const double upperClipValue = range.upper + (reversed ? 0 : range.size()*0.05+clipMargin); // clip slightly outside of actual range to avoid line thicknesses to peek into visible circle
35374  const double lowerClipValue = range.lower - (reversed ? range.size()*0.05+clipMargin : 0); // clip slightly outside of actual range to avoid line thicknesses to peek into visible circle
35375  const double maxKeySkip = qAsin(qSqrt(clipMargin*(clipMargin+2*range.size()))/(range.size()+clipMargin))/M_PI*mKeyAxis->range().size(); // the maximum angle between two points on outer circle (r=clipValue+clipMargin) before connecting line becomes tangent to inner circle (r=clipValue)
35376  double skipBegin = 0;
35377  bool belowRange = false;
35378  bool aboveRange = false;
35380  while (it != end)
35381  {
35382  if (it->value < lowerClipValue)
35383  {
35384  if (aboveRange) // jumped directly from above to below visible range, draw previous point so entry angle is correct
35385  {
35386  aboveRange = false;
35387  if (!reversed) // TODO: with inner radius, we'll need else case here with projected border point
35388  lineData->append(*(it-1));
35389  }
35390  if (!belowRange)
35391  {
35392  skipBegin = it->key;
35393  lineData->append(QCPGraphData(it->key, lowerClipValue));
35394  belowRange = true;
35395  }
35396  if (it->key-skipBegin > maxKeySkip) // add dummy point if we're exceeding the maximum skippable angle (to prevent unintentional intersections with visible circle)
35397  {
35398  skipBegin += maxKeySkip;
35399  lineData->append(QCPGraphData(skipBegin, lowerClipValue));
35400  }
35401  } else if (it->value > upperClipValue)
35402  {
35403  if (belowRange) // jumped directly from below to above visible range, draw previous point so entry angle is correct (if lower means outer, so if reversed axis)
35404  {
35405  belowRange = false;
35406  if (reversed)
35407  lineData->append(*(it-1));
35408  }
35409  if (!aboveRange)
35410  {
35411  skipBegin = it->key;
35412  lineData->append(QCPGraphData(it->key, upperClipValue));
35413  aboveRange = true;
35414  }
35415  if (it->key-skipBegin > maxKeySkip) // add dummy point if we're exceeding the maximum skippable angle (to prevent unintentional intersections with visible circle)
35416  {
35417  skipBegin += maxKeySkip;
35418  lineData->append(QCPGraphData(skipBegin, upperClipValue));
35419  }
35420  } else // value within bounds where we don't optimize away points
35421  {
35422  if (aboveRange)
35423  {
35424  aboveRange = false;
35425  if (!reversed)
35426  lineData->append(*(it-1)); // just entered from above, draw previous point so entry angle is correct (if above means outer, so if not reversed axis)
35427  }
35428  if (belowRange)
35429  {
35430  belowRange = false;
35431  if (reversed)
35432  lineData->append(*(it-1)); // just entered from below, draw previous point so entry angle is correct (if below means outer, so if reversed axis)
35433  }
35434  lineData->append(*it); // inside visible circle, add point normally
35435  }
35436  ++it;
35437  }
35438  // to make fill not erratic, add last point normally if it was outside visible circle:
35439  if (aboveRange)
35440  {
35441  aboveRange = false;
35442  if (!reversed)
35443  lineData->append(*(it-1)); // just entered from above, draw previous point so entry angle is correct (if above means outer, so if not reversed axis)
35444  }
35445  if (belowRange)
35446  {
35447  belowRange = false;
35448  if (reversed)
35449  lineData->append(*(it-1)); // just entered from below, draw previous point so entry angle is correct (if below means outer, so if reversed axis)
35450  }
35451 }
35452 
35454 {
35455  scatterData->clear();
35456 
35457  const QCPRange range = mValueAxis->range();
35458  bool reversed = mValueAxis->rangeReversed();
35459  const double clipMargin = range.size()*0.05;
35460  const double upperClipValue = range.upper + (reversed ? 0 : clipMargin); // clip slightly outside of actual range to avoid scatter size to peek into visible circle
35461  const double lowerClipValue = range.lower - (reversed ? clipMargin : 0); // clip slightly outside of actual range to avoid scatter size to peek into visible circle
35463  while (it != end)
35464  {
35465  if (it->value > lowerClipValue && it->value < upperClipValue)
35466  scatterData->append(*it);
35467  ++it;
35468  }
35469 }
35470 
35481 QVector<QPointF> QCPPolarGraph::dataToLines(const QVector<QCPGraphData> &data) const
35482 {
35483  QVector<QPointF> result;
35486  if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; }
35487 
35488  // transform data points to pixels:
35489  result.resize(data.size());
35490  for (int i=0; i<data.size(); ++i)
35491  result[i] = mValueAxis->coordToPixel(data.at(i).key, data.at(i).value);
35492  return result;
35493 }
35494 /* end of 'src/polar/polargraph.cpp' */
35495 
35496 
QCPGraph::getNonNanSegments
QVector< QCPDataRange > getNonNanSegments(const QVector< QPointF > *lineData, Qt::Orientation keyOrientation) const
Definition: qcustomplot.cpp:21964
QCPAxisRect::width
int width() const
Definition: qcustomplot.h:4953
QCPItemPosition::setTypeX
void setTypeX(PositionType type)
Definition: qcustomplot.cpp:12289
QCPLabelPainterPrivate::amSkewedUpright
@ amSkewedUpright
Definition: qcustomplot.h:1565
QCPPolarAxisRadial::setRange
Q_SLOT void setRange(const QCPRange &range)
Definition: qcustomplot.cpp:31234
QCPColorMap::gradient
QCPColorGradient gradient() const
Definition: qcustomplot.h:6063
QCPItemRect::aiLeft
@ aiLeft
Definition: qcustomplot.h:6567
QCPPolarLegendItem::mPolarGraph
QCPPolarGraph * mPolarGraph
Definition: qcustomplot.h:7586
QCPErrorBars::mErrorType
ErrorType mErrorType
Definition: qcustomplot.h:6356
QCP::PlottingHint
PlottingHint
Definition: qcustomplot.h:256
QCPFinancial::setPenPositive
void setPenPositive(const QPen &pen)
Definition: qcustomplot.cpp:27202
QCPGrid::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7949
QCPGraph::getOptimizedScatterData
virtual void getOptimizedScatterData(QVector< QCPGraphData > *scatterData, QCPGraphDataContainer::const_iterator begin, QCPGraphDataContainer::const_iterator end) const
Definition: qcustomplot.cpp:21753
QCPVector2D::x
double x() const
Definition: qcustomplot.h:414
QCPPolarAxisAngular::setTickLengthOut
void setTickLengthOut(int outside)
Definition: qcustomplot.cpp:33565
QCPPolarGraph::pixelsToCoords
void pixelsToCoords(double x, double y, double &key, double &value) const
Definition: qcustomplot.cpp:34746
QCPLegend::SelectablePart
SelectablePart
Definition: qcustomplot.h:5126
QCPSelectionDecorator::mPen
QPen mPen
Definition: qcustomplot.h:3441
QCP::phFastPolylines
@ phFastPolylines
Definition: qcustomplot.h:257
QCPAbstractLegendItem::setFont
void setFont(const QFont &font)
Definition: qcustomplot.cpp:18752
QCPPolarAxisRadial::rangeDrag
bool rangeDrag() const
Definition: qcustomplot.h:7014
QCPPolarAxisRadial::setSubTickLengthOut
void setSubTickLengthOut(int outside)
Definition: qcustomplot.cpp:31711
QCPPolarAxisAngular::setBackgroundScaledMode
void setBackgroundScaledMode(Qt::AspectRatioMode mode)
Definition: qcustomplot.cpp:33146
QCPAxisRect::height
int height() const
Definition: qcustomplot.h:4954
QCPLayoutElement::scrInnerRect
@ scrInnerRect
Minimum/Maximum size constraints apply to inner rect.
Definition: qcustomplot.h:1235
QCPItemPosition::type
PositionType type() const
Definition: qcustomplot.h:3631
QCPAxisTickerFixed::ssMultiples
@ ssMultiples
An integer multiple of the specified tick step is allowed. The used factor follows the base class pro...
Definition: qcustomplot.h:1874
QCPAxis::setSelectedSubTickPen
void setSelectedSubTickPen(const QPen &pen)
Definition: qcustomplot.cpp:9069
QCPItemPixmap::aiLeft
@ aiLeft
Definition: qcustomplot.h:6789
QCPLayoutGrid::mWrap
int mWrap
Definition: qcustomplot.h:1424
QCPPolarAxisAngular::mGrid
QCPPolarGrid * mGrid
Definition: qcustomplot.h:7442
QCPItemPixmap::QCPItemPixmap
QCPItemPixmap(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:30121
QCPPolarAxisAngular::radialAxes
QList< QCPPolarAxisRadial * > radialAxes() const
Definition: qcustomplot.cpp:32694
QCPGrid::mAntialiasedSubGrid
bool mAntialiasedSubGrid
Definition: qcustomplot.h:2067
QCPColorGradient::mNanHandling
NanHandling mNanHandling
Definition: qcustomplot.h:4796
QCPScatterStyle::setShape
void setShape(ScatterShape shape)
Definition: qcustomplot.cpp:10786
QCPItemTracer::tsCircle
@ tsCircle
A circle.
Definition: qcustomplot.h:6839
QCPItemBracket::mStyle
BracketStyle mStyle
Definition: qcustomplot.h:6952
QCPVector2D::toPointF
QPointF toPointF() const
Definition: qcustomplot.h:428
QCPPolarGrid::mRadialZeroLinePen
QPen mRadialZeroLinePen
Definition: qcustomplot.h:7545
QCPLabelPainterPrivate::getTickLabelData
LabelData getTickLabelData(const QFont &font, const QColor &color, double rotation, AnchorSide side, const QString &text) const
Definition: qcustomplot.cpp:5836
QCPLayerable::QCPAxisRect
friend class QCPAxisRect
Definition: qcustomplot.h:787
QCPPolarAxisRadial::mSubTicks
bool mSubTicks
Definition: qcustomplot.h:7157
QCPLabelPainterPrivate::mAnchorSide
AnchorSide mAnchorSide
Definition: qcustomplot.h:1654
QCPAxisRect::setRangeZoom
void setRangeZoom(Qt::Orientations orientations)
Definition: qcustomplot.cpp:18226
QCPBars::addData
void addData(const QVector< double > &keys, const QVector< double > &values, bool alreadySorted=false)
Definition: qcustomplot.cpp:24548
QCPDataSelection::dataRange
QCPDataRange dataRange(int index=0) const
Definition: qcustomplot.cpp:2544
QCPGrid::mSubGridPen
QPen mSubGridPen
Definition: qcustomplot.h:2068
QCPLabelPainterPrivate::LabelData
Definition: qcustomplot.h:1639
QCPItemAnchor::addChildY
void addChildY(QCPItemPosition *pos)
Definition: qcustomplot.cpp:12122
QCustomPlot::mBackgroundBrush
QBrush mBackgroundBrush
Definition: qcustomplot.h:3945
QCPAxis::setSubTicks
void setSubTicks(bool show)
Definition: qcustomplot.cpp:8830
QCPAxis::setTicks
void setTicks(bool show)
Definition: qcustomplot.cpp:8584
QCPItemStraightLine::mPen
QPen mPen
Definition: qcustomplot.h:6412
QCP::iRangeDrag
@ iRangeDrag
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes)
Definition: qcustomplot.h:273
QCPLabelPainterPrivate::LabelData::color
QColor color
Definition: qcustomplot.h:1649
QCPRange::lower
double lower
Definition: qcustomplot.h:799
QCPFinancial::selectTestRect
virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27275
QCPFinancial::csOhlc
@ csOhlc
Open-High-Low-Close bar representation.
Definition: qcustomplot.h:6183
QCPAxis::setTickLabels
void setTickLabels(bool show)
Definition: qcustomplot.cpp:8596
QCPAbstractPlottable::mAntialiasedFill
bool mAntialiasedFill
Definition: qcustomplot.h:3529
QCPAxisTickerTime::TimeUnit
TimeUnit
Definition: qcustomplot.h:1820
QCPItemTracer::mPen
QPen mPen
Definition: qcustomplot.h:6879
QCPAbstractPlottable::addToLegend
bool addToLegend(QCPLegend *legend)
Definition: qcustomplot.cpp:11806
QCPColorGradient::ColorInterpolation
ColorInterpolation
Definition: qcustomplot.h:4724
QCPAxisRect::rangeZoomAxes
QList< QCPAxis * > rangeZoomAxes(Qt::Orientation orientation)
Definition: qcustomplot.cpp:18159
QCPAxis::setSelectableParts
Q_SLOT void setSelectableParts(const QCPAxis::SelectableParts &selectableParts)
Definition: qcustomplot.cpp:8413
QCPLabelPainterPrivate::mLetterCapHeight
int mLetterCapHeight
Definition: qcustomplot.h:1669
QCPErrorBars::QCPErrorBars
QCPErrorBars(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:27959
QCPLabelPainterPrivate::artNormal
@ artNormal
Definition: qcustomplot.h:1573
QCPPolarGraph::selectable
QCP::SelectionType selectable() const
Definition: qcustomplot.h:7629
QCPLabelPainterPrivate::color
QColor color() const
Definition: qcustomplot.h:1615
QCustomPlot::mItems
QList< QCPAbstractItem * > mItems
Definition: qcustomplot.h:3939
QCPItemEllipse::topLeft
QCPItemPosition *const topLeft
Definition: qcustomplot.h:6713
QCPPolarAxisAngular::mInsetLayout
QCPLayoutInset * mInsetLayout
Definition: qcustomplot.h:7404
QCPFinancial::~QCPFinancial
virtual ~QCPFinancial() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27079
QCPColorGradient::nhNone
@ nhNone
NaN data points are not explicitly handled and shouldn't occur in the data (this gives slight perform...
Definition: qcustomplot.h:4734
QCustomPlot::mSelectionTolerance
int mSelectionTolerance
Definition: qcustomplot.h:3943
QCP::aeOther
@ aeOther
0x8000 Other elements that don't fit into any of the existing categories
Definition: qcustomplot.h:245
QCPGraph::findIndexAboveY
int findIndexAboveY(const QVector< QPointF > *data, double y) const
Definition: qcustomplot.cpp:22361
QCPPolarAxisAngular::mLabel
QString mLabel
Definition: qcustomplot.h:7415
QCPItemPixmap::bottomRight
QCPItemPosition *const bottomRight
Definition: qcustomplot.h:6780
QCPPolarAxisAngular::mDragRadialStart
QList< QCPRange > mDragRadialStart
Definition: qcustomplot.h:7452
QCPColorMapData::QCPColorMapData
QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange)
Definition: qcustomplot.cpp:25813
QCPSelectionDecorator::scatterStyle
QCPScatterStyle scatterStyle() const
Definition: qcustomplot.h:3421
QCPLayoutGrid::indexToRowCol
void indexToRowCol(int index, int &row, int &column) const
Definition: qcustomplot.cpp:4557
QCPAxisTickerPi::FractionStyle
FractionStyle
Definition: qcustomplot.h:1952
QCPPolarAxisAngular::removeGraph
bool removeGraph(QCPPolarGraph *graph)
Definition: qcustomplot.cpp:33001
QCPAbstractPlottable1D
A template base class for plottables with one-dimensional data.
Definition: qcustomplot.h:4141
QCPColorMapData::keySize
int keySize() const
Definition: qcustomplot.h:5994
QCPColorMapData::mDataModified
bool mDataModified
Definition: qcustomplot.h:6034
QCPAxisRect::setupFullAxesBox
void setupFullAxesBox(bool connectRanges=false)
Definition: qcustomplot.cpp:17831
QCPAbstractPlottable::applyFillAntialiasingHint
void applyFillAntialiasingHint(QCPPainter *painter) const
Definition: qcustomplot.cpp:11925
QCPItemTracer::setStyle
void setStyle(TracerStyle style)
Definition: qcustomplot.cpp:30483
QCPFinancial::ohlcSelectTest
double ohlcSelectTest(const QPointF &pos, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, QCPFinancialDataContainer::const_iterator &closestDataPoint) const
Definition: qcustomplot.cpp:27688
QCPAxisTicker::getTickLabel
virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision)
Definition: qcustomplot.cpp:6293
QCPAxis::mAADragBackup
QCP::AntialiasedElements mAADragBackup
Definition: qcustomplot.h:2347
QCPGraph::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:21101
QCPAbstractPaintBuffer::setSize
void setSize(const QSize &size)
Definition: qcustomplot.cpp:600
QCPPolarAxisRadial::mSelectedTickLabelFont
QFont mSelectedTickLabelFont
Definition: qcustomplot.h:7149
QCPPlottableInterface1D::dataMainValue
virtual double dataMainValue(int index) const =0
QCPItemPosition::ptViewportRatio
@ ptViewportRatio
Definition: qcustomplot.h:3617
QCustomPlot::mGraphs
QList< QCPGraph * > mGraphs
Definition: qcustomplot.h:3938
QCPAbstractLegendItem::mSelectedTextColor
QColor mSelectedTextColor
Definition: qcustomplot.h:5058
QCPColorGradient::ciRGB
@ ciRGB
Color channels red, green and blue are linearly interpolated.
Definition: qcustomplot.h:4724
QCPAxis::mLabelColor
QColor mLabelColor
Definition: qcustomplot.h:2314
QCPItemText::setSelectedFont
void setSelectedFont(const QFont &font)
Definition: qcustomplot.cpp:29689
QCPItemRect::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6570
QCPErrorBars::ErrorType
ErrorType
Definition: qcustomplot.h:6307
QCPColorMap::mUndersampledMapImage
QImage mUndersampledMapImage
Definition: qcustomplot.h:6100
QCPDataRange::expanded
QCPDataRange expanded(const QCPDataRange &other) const
Definition: qcustomplot.cpp:2299
QCPAxisRect::left
int left() const
Definition: qcustomplot.h:4949
QCPAxisTicker
The base class tick generator used by QCPAxis to create tick positions and tick labels.
Definition: qcustomplot.h:1697
QCPAbstractItem::position
QCPItemPosition * position(const QString &name) const
Definition: qcustomplot.cpp:13032
QCPPolarAxisAngular::mLabelPainter
QCPLabelPainterPrivate mLabelPainter
Definition: qcustomplot.h:7454
QCPPolarAxisAngular::setSelectedSubTickPen
void setSelectedSubTickPen(const QPen &pen)
Definition: qcustomplot.cpp:33788
QCPColorGradient::loadPreset
void loadPreset(GradientPreset preset)
Definition: qcustomplot.cpp:16859
QCPAxis::mDragStartRange
QCPRange mDragStartRange
Definition: qcustomplot.h:2346
QCPGrid::setAntialiasedZeroLine
void setAntialiasedZeroLine(bool enabled)
Definition: qcustomplot.cpp:7894
QCPLayoutElement::setMinimumMargins
void setMinimumMargins(const QMargins &margins)
Definition: qcustomplot.cpp:3278
QCPPolarGrid::drawAngularGrid
void drawAngularGrid(QCPPainter *painter, const QPointF &center, double radius, const QVector< QPointF > &ticksCosSin, const QPen &pen)
Definition: qcustomplot.cpp:34304
QCPPolarGraph::rescaleKeyAxis
void rescaleKeyAxis(bool onlyEnlarge=false) const
Definition: qcustomplot.cpp:34774
QCPItemText::mSelectedBrush
QBrush mSelectedBrush
Definition: qcustomplot.h:6659
QCPSelectionDecoratorBracket::mBracketHeight
int mBracketHeight
Definition: qcustomplot.h:4869
QCPItemTracer::~QCPItemTracer
virtual ~QCPItemTracer() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30424
QCPLabelPainterPrivate::drawTickLabel
void drawTickLabel(QCPPainter *painter, const QPointF &tickPos, const QString &text)
Definition: qcustomplot.cpp:5573
QCPPolarAxisAngular::spTickLabels
@ spTickLabels
Tick labels (numbers) of this axis (as a whole, not individually)
Definition: qcustomplot.h:7234
QCPAxis::setSubTickLength
void setSubTickLength(int inside, int outside=0)
Definition: qcustomplot.cpp:8847
QCPPolarAxisAngular::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:33985
QCPGraph::findIndexAboveX
int findIndexAboveX(const QVector< QPointF > *data, double x) const
Definition: qcustomplot.cpp:22315
QCustomPlot::LayerInsertMode
LayerInsertMode
Definition: qcustomplot.h:3774
QCPAxisTickerLog::mSubTickCount
int mSubTickCount
Definition: qcustomplot.h:2018
QCPItemEllipse::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:29958
QCPLegend::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19550
QCPSelectionRect::startSelection
virtual void startSelection(QMouseEvent *event)
Definition: qcustomplot.cpp:2918
QCPItemPosition::mKeyAxis
QPointer< QCPAxis > mKeyAxis
Definition: qcustomplot.h:3661
QCPAxisRect::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18010
QCPDataRange::end
int end() const
Definition: qcustomplot.h:925
QCP::iSelectPlottablesBeyondAxisRect
@ iSelectPlottablesBeyondAxisRect
0x100 When performing plottable selection/hit tests, this flag extends the sensitive area beyond the ...
Definition: qcustomplot.h:281
QCPVector2D::distanceSquaredToLine
double distanceSquaredToLine(const QCPVector2D &start, const QCPVector2D &end) const
Definition: qcustomplot.cpp:190
QCPAxisRect::axes
QList< QCPAxis * > axes(QCPAxis::AxisTypes types) const
Definition: qcustomplot.cpp:17625
QCPTextElement::mTextBoundingRect
QRect mTextBoundingRect
Definition: qcustomplot.h:5290
QCPLegend::mSelectedBrush
QBrush mSelectedBrush
Definition: qcustomplot.h:5199
QCPPolarGraph::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
Definition: qcustomplot.cpp:35014
QCPBars::getBarRect
QRectF getBarRect(double key, double value) const
Definition: qcustomplot.cpp:24941
QCPAbstractItem::QCPItemAnchor
friend class QCPItemAnchor
Definition: qcustomplot.h:3744
QCustomPlot::interactions
const QCP::Interactions interactions() const
Definition: qcustomplot.h:3804
QCPItemRect::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:29540
QCP::aeGrid
@ aeGrid
0x0002 Grid lines
Definition: qcustomplot.h:236
QCPAxisTickerText::getTickStep
virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7342
QCPAbstractItem::mSelected
bool mSelected
Definition: qcustomplot.h:3721
QCPLegend::mTextColor
QColor mTextColor
Definition: qcustomplot.h:5194
QCPAbstractPlottable::mBrush
QBrush mBrush
Definition: qcustomplot.h:3531
QCPLayoutInset::ipFree
@ ipFree
The element may be positioned/sized arbitrarily, see setInsetRect.
Definition: qcustomplot.h:1444
QCPAxisTicker::cleanMantissa
double cleanMantissa(double input) const
Definition: qcustomplot.cpp:6452
QCustomPlot::sizeHint
virtual QSize sizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15456
QCPLabelPainterPrivate::AnchorSide
AnchorSide
Definition: qcustomplot.h:1581
QCPBars::WidthType
WidthType
Definition: qcustomplot.h:5795
QCPLayoutInset::insetRect
QRectF insetRect(int index) const
Definition: qcustomplot.cpp:4935
QCPItemPosition::setAxes
void setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:12636
QCPErrorBars::getErrorBarLines
void getErrorBarLines(QCPErrorBarsDataContainer::const_iterator it, QVector< QLineF > &backbones, QVector< QLineF > &whiskers) const
Definition: qcustomplot.cpp:28577
QCPCurve::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:22859
QCPAxisTickerTime::getSubTickCount
virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7012
QCPAxis::getTickPen
QPen getTickPen() const
Definition: qcustomplot.cpp:9755
QCPItemPixmap::setPixmap
void setPixmap(const QPixmap &pixmap)
Definition: qcustomplot.cpp:30150
QCPAxisTickerFixed::setTickStep
void setTickStep(double step)
Definition: qcustomplot.cpp:7127
QCPAxis::setSelectedTickLabelColor
void setSelectedTickLabelColor(const QColor &color)
Definition: qcustomplot.cpp:9026
QCPAbstractLegendItem::setTextColor
void setTextColor(const QColor &color)
Definition: qcustomplot.cpp:18762
QCustomPlot::mReplotTime
double mReplotTime
Definition: qcustomplot.h:3967
QCPAxis::setPadding
void setPadding(int padding)
Definition: qcustomplot.cpp:8974
QCPDataRange::isValid
bool isValid() const
Definition: qcustomplot.h:934
QCPAxis::mSelectedParts
SelectableParts mSelectedParts
Definition: qcustomplot.h:2307
qcustomplot.h
QCPItemBracket::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:30795
QCPItemText::aiBottomRight
@ aiBottomRight
Definition: qcustomplot.h:6654
QCPAbstractPlottable::mName
QString mName
Definition: qcustomplot.h:3528
QCustomPlot::legend
QCPLegend * legend
Definition: qcustomplot.h:3908
QCPMarginGroup::commonMargin
virtual int commonMargin(QCP::MarginSide side) const
Definition: qcustomplot.cpp:3099
QCPSelectionDecorator::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:11071
QCPPolarAxisAngular::mSubTickVectorCosSin
QVector< QPointF > mSubTickVectorCosSin
Definition: qcustomplot.h:7449
QCPBarsData
Holds the data of one single data point (one bar) for QCPBars.
Definition: qcustomplot.h:5745
QCP::msBottom
@ msBottom
0x08 bottom margin
Definition: qcustomplot.h:220
QCPLayoutElement::mParentLayout
QCPLayout * mParentLayout
Definition: qcustomplot.h:1279
QCPAbstractLegendItem
The abstract base class for all entries in a QCPLegend.
Definition: qcustomplot.h:5013
QCP::msAll
@ msAll
0xFF all margins
Definition: qcustomplot.h:221
QCP::iRangeZoom
@ iRangeZoom
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom,...
Definition: qcustomplot.h:274
QCPAxis::AxisType
AxisType
Definition: qcustomplot.h:2138
QCPLegend::~QCPLegend
virtual ~QCPLegend() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19081
QCPScatterStyle::spShape
@ spShape
0x08 The shape property, see setShape
Definition: qcustomplot.h:2478
QCPAbstractLegendItem::mTextColor
QColor mTextColor
Definition: qcustomplot.h:5056
QCPAxisTicker::getTickStep
virtual double getTickStep(const QCPRange &range)
Definition: qcustomplot.cpp:6217
QCPItemPosition::setCoords
void setCoords(double key, double value)
Definition: qcustomplot.cpp:12514
QCPCurve::getOptimizedPoint
QPointF getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const
Definition: qcustomplot.cpp:23278
QCPAxisTickerLog::createTickVector
virtual QVector< double > createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7788
QCPAxisTicker::generate
virtual void generate(const QCPRange &range, const QLocale &locale, QChar formatChar, int precision, QVector< double > &ticks, QVector< double > *subTicks, QVector< QString > *tickLabels)
Definition: qcustomplot.cpp:6182
QCPPolarAxisAngular::mSubTickLengthOut
int mSubTickLengthOut
Definition: qcustomplot.h:7431
QCPColorScale::setBarWidth
void setBarWidth(int width)
Definition: qcustomplot.cpp:20307
QCPAxis::setupTickVectors
void setupTickVectors()
Definition: qcustomplot.cpp:9730
QCPPolarAxisRadial::setSubTicks
void setSubTicks(bool show)
Definition: qcustomplot.cpp:31667
QCPSelectionDecoratorBracket::bsPlus
@ bsPlus
A plus is drawn.
Definition: qcustomplot.h:4832
QCPColorMapData::mData
double * mData
Definition: qcustomplot.h:6031
QCPItemEllipse::mainBrush
QBrush mainBrush() const
Definition: qcustomplot.cpp:30087
QCPErrorBars::findEnd
virtual int findEnd(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28279
QCPLayoutInset::updateLayout
virtual void updateLayout() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4995
QCPItemTracer::setSize
void setSize(double size)
Definition: qcustomplot.cpp:30472
QCPSelectionDecoratorBracket::setBracketHeight
void setBracketHeight(int height)
Definition: qcustomplot.cpp:17192
QCPPolarAxisAngular::mRangeZoomFactor
double mRangeZoomFactor
Definition: qcustomplot.h:7407
QCPBarsGroup::mSpacingType
SpacingType mSpacingType
Definition: qcustomplot.h:5725
QCPLayoutGrid::foColumnsFirst
@ foColumnsFirst
Columns are filled first, and a new element is wrapped to the next row if the column count would exce...
Definition: qcustomplot.h:1369
QCPAxisTickerDateTime::mTimeZone
QTimeZone mTimeZone
Definition: qcustomplot.h:1793
QCP::aeScatters
@ aeScatters
0x0080 Scatter symbols of plottables (excluding scatter symbols of type ssPixmap)
Definition: qcustomplot.h:242
QCPAbstractPlottable::rescaleKeyAxis
void rescaleKeyAxis(bool onlyEnlarge=false) const
Definition: qcustomplot.cpp:11717
QCPLegend::mFont
QFont mFont
Definition: qcustomplot.h:5193
QCPItemCurve::setHead
void setHead(const QCPLineEnding &head)
Definition: qcustomplot.cpp:29309
QCPLayoutElement::elements
virtual QList< QCPLayoutElement * > elements(bool recursive) const
Definition: qcustomplot.cpp:3508
QCPLineEnding::boundingDistance
double boundingDistance() const
Definition: qcustomplot.cpp:5264
QCPBars::~QCPBars
virtual ~QCPBars() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24424
QCustomPlot::setAutoAddPlottableToLegend
void setAutoAddPlottableToLegend(bool on)
Definition: qcustomplot.cpp:13805
QCPPainter
QPainter subclass used internally.
Definition: qcustomplot.h:480
QCPItemTracer::position
QCPItemPosition *const position
Definition: qcustomplot.h:6875
QCPAxisTickerPi::fsUnicodeFractions
@ fsUnicodeFractions
Fractions are written using sub- and superscript UTF-8 digits and the fraction symbol.
Definition: qcustomplot.h:1954
QCPPolarAxisAngular::getTickLabelColor
QColor getTickLabelColor() const
Definition: qcustomplot.cpp:33929
QCPItemPosition::mPositionTypeX
PositionType mPositionTypeX
Definition: qcustomplot.h:3660
QCPLayer::removeChild
void removeChild(QCPLayerable *layerable)
Definition: qcustomplot.cpp:1247
QCPPolarGrid::gtNone
@ gtNone
Definition: qcustomplot.h:7507
QCPPolarAxisAngular::mCenter
QPointF mCenter
Definition: qcustomplot.h:7439
QCPAxisRect::rangeDragAxis
QCPAxis * rangeDragAxis(Qt::Orientation orientation)
Definition: qcustomplot.cpp:18106
QCPPolarAxisAngular::setRangeDrag
void setRangeDrag(bool enabled)
Definition: qcustomplot.cpp:33151
QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate
QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale)
Definition: qcustomplot.cpp:20550
QCPAxisRect
Holds multiple axes and arranges them in a rectangular shape.
Definition: qcustomplot.h:4887
QCPCurve::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:22871
QCPErrorBars::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28406
QCPLayout::clear
void clear()
Definition: qcustomplot.cpp:3776
QCPErrorBars::etKeyError
@ etKeyError
The errors are for the key dimension (bars appear parallel to the key axis)
Definition: qcustomplot.h:6307
QCPLayout::updateLayout
virtual void updateLayout()
Definition: qcustomplot.cpp:3814
QCPAxis::offset
int offset() const
Definition: qcustomplot.cpp:8334
QCPItemBracket::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30874
QCPLayoutElement::mMinimumSize
QSize mMinimumSize
Definition: qcustomplot.h:1280
QCPLayerable::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
Definition: qcustomplot.cpp:1776
QCPItemAnchor::addChildX
void addChildX(QCPItemPosition *pos)
Definition: qcustomplot.cpp:12094
QCPBars::barsGroup
QCPBarsGroup * barsGroup() const
Definition: qcustomplot.h:5807
QCPAxis
Manages a single axis inside a QCustomPlot.
Definition: qcustomplot.h:2085
QCPItemEllipse::aiTopLeftRim
@ aiTopLeftRim
Definition: qcustomplot.h:6726
QCPFinancial::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27412
QCPScatterStyle::ssDiamond
@ ssDiamond
\enumimage{ssDiamond.png} a diamond
Definition: qcustomplot.h:2499
QCPLayoutGrid::hasElement
bool hasElement(int row, int column)
Definition: qcustomplot.cpp:4221
QCPColorScale::setLabel
void setLabel(const QString &str)
Definition: qcustomplot.cpp:20292
QCPItemRect::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29500
QCPAxis::setTickLabelRotation
void setTickLabelRotation(double degrees)
Definition: qcustomplot.cpp:8653
QCPAbstractItem::mPositions
QList< QCPItemPosition * > mPositions
Definition: qcustomplot.h:3719
QCPPolarAxisRadial::getLabelColor
QColor getLabelColor() const
Definition: qcustomplot.cpp:32422
QCPItemPixmap::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:30185
QCPLegend::mSelectedIconBorderPen
QPen mSelectedIconBorderPen
Definition: qcustomplot.h:5198
QCPPolarAxisAngular::mSelectedLabelColor
QColor mSelectedLabelColor
Definition: qcustomplot.h:7417
QCPPolarAxisRadial::angularAxis
QCPPolarAxisAngular * angularAxis() const
Definition: qcustomplot.h:7018
QCPLabelPainterPrivate::setRotation
void setRotation(double rotation)
Definition: qcustomplot.cpp:5543
QCPItemPixmap::topLeft
QCPItemPosition *const topLeft
Definition: qcustomplot.h:6779
QCPPlottableInterface1D::dataMainKey
virtual double dataMainKey(int index) const =0
QCPTextElement::font
QFont font() const
Definition: qcustomplot.h:5253
QCPCurve::setData
void setData(QSharedPointer< QCPCurveDataContainer > data)
Definition: qcustomplot.cpp:22651
QCPVector2D::lengthSquared
double lengthSquared() const
Definition: qcustomplot.h:425
QCPErrorBars::selectTestRect
virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28230
QCPGraph::pointDistance
double pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const
Definition: qcustomplot.cpp:22387
QCPItemAnchor::mParentPlot
QCustomPlot * mParentPlot
Definition: qcustomplot.h:3584
QCPColorScale::setRangeDrag
void setRangeDrag(bool enabled)
Definition: qcustomplot.cpp:20318
QCPColorGradient::setNanColor
void setNanColor(const QColor &color)
Definition: qcustomplot.cpp:16647
QCPAxisTickerDateTime::QCPAxisTickerDateTime
QCPAxisTickerDateTime()
Definition: qcustomplot.cpp:6523
QCPItemTracer::mainBrush
QBrush mainBrush() const
Definition: qcustomplot.cpp:30727
QCPItemLine::mTail
QCPLineEnding mTail
Definition: qcustomplot.h:6462
QCPLineEnding::setStyle
void setStyle(EndingStyle style)
Definition: qcustomplot.cpp:5215
QCPLabelPainterPrivate::font
QFont font() const
Definition: qcustomplot.h:1614
QCPPolarAxisRadial::mDragStartRange
QCPRange mDragStartRange
Definition: qcustomplot.h:7174
QCPLabelPainterPrivate::mSubstituteExponent
bool mSubstituteExponent
Definition: qcustomplot.h:1661
QCPItemBracket::setLength
void setLength(double length)
Definition: qcustomplot.cpp:30818
QCPSelectionDecorator::setScatterStyle
void setScatterStyle(const QCPScatterStyle &scatterStyle, QCPScatterStyle::ScatterProperties usedProperties=QCPScatterStyle::spPen)
Definition: qcustomplot.cpp:11091
QCPPainter::mModes
PainterModes mModes
Definition: qcustomplot.h:524
QCPItemPosition::setParentAnchorY
bool setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false)
Definition: qcustomplot.cpp:12439
QCPColorMap::rescaleDataRange
void rescaleDataRange(bool recalculateDataBounds=false)
Definition: qcustomplot.cpp:26597
QCPAxisTicker::pickClosest
double pickClosest(double target, const QVector< double > &candidates) const
Definition: qcustomplot.cpp:6419
QCPLabelPainterPrivate::skewedAnchorSide
AnchorSide skewedAnchorSide(const QPointF &tickPos, double sideExpandHorz, double sideExpandVert) const
Definition: qcustomplot.cpp:5992
QCPErrorBars::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28302
QCPLabelPainterPrivate::mAnchorMode
AnchorMode mAnchorMode
Definition: qcustomplot.h:1653
QCPAxis::tickLabels
bool tickLabels() const
Definition: qcustomplot.h:2187
QCPAxisRect::mInsetLayout
QCPLayoutInset * mInsetLayout
Definition: qcustomplot.h:4973
QCPItemText::mSelectedColor
QColor mSelectedColor
Definition: qcustomplot.h:6657
QCPAbstractItem::anchorPixelPosition
virtual QPointF anchorPixelPosition(int anchorId) const
Definition: qcustomplot.cpp:13166
QCPPolarAxisAngular::lmRotated
@ lmRotated
Definition: qcustomplot.h:7245
QCPAxisRect::updateAxesOffset
void updateAxesOffset(QCPAxis::AxisType type)
Definition: qcustomplot.cpp:18452
QCPItemBracket::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:30805
QCPPolarAxisRadial::mTickVectorLabels
QVector< QString > mTickVectorLabels
Definition: qcustomplot.h:7171
QCPPlottableLegendItem::getTextColor
QColor getTextColor() const
Definition: qcustomplot.cpp:18929
QCPColorMapData::valueRange
QCPRange valueRange() const
Definition: qcustomplot.h:5997
QCustomPlot::mSelectionRectMode
QCP::SelectionRectMode mSelectionRectMode
Definition: qcustomplot.h:3953
QCPPolarAxisAngular::mTickLengthIn
int mTickLengthIn
Definition: qcustomplot.h:7431
QCPLabelPainterPrivate::setAnchorSide
void setAnchorSide(AnchorSide side)
Definition: qcustomplot.cpp:5504
QCPItemText::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:29888
QCPAbstractPlottable::selectionChanged
void selectionChanged(bool selected)
Definition: moc_qcustomplot.cpp:2950
QCPSelectionRect::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:2894
QCPLegend::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19592
QCPPolarAxisAngular::mLabelFont
QFont mLabelFont
Definition: qcustomplot.h:7416
QCustomPlot::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15636
QCPLayoutGrid::mRowSpacing
int mRowSpacing
Definition: qcustomplot.h:1423
QCPAxis::setRange
Q_SLOT void setRange(const QCPRange &range)
Definition: qcustomplot.cpp:8385
QCPColorGradient::QCPColorGradient
QCPColorGradient()
Definition: qcustomplot.cpp:16526
QCPAxisTicker::createLabelVector
virtual QVector< QString > createLabelVector(const QVector< double > &ticks, const QLocale &locale, QChar formatChar, int precision)
Definition: qcustomplot.cpp:6361
QCPPolarAxisRadial::mTickLabelColor
QColor mTickLabelColor
Definition: qcustomplot.h:7150
QCPAxis::mGrid
QCPGrid * mGrid
Definition: qcustomplot.h:2337
QCPBars::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24744
QCPLayoutElement::parentPlotInitialized
virtual void parentPlotInitialized(QCustomPlot *parentPlot) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:3550
QCustomPlot::mReplotting
bool mReplotting
Definition: qcustomplot.h:3965
QCPAxis::setLabel
void setLabel(const QString &str)
Definition: qcustomplot.cpp:8941
QCPLayer::lmBuffered
@ lmBuffered
Layer has its own paint buffer and may be replotted individually (see replot).
Definition: qcustomplot.h:668
QCPPolarGraph
A radial graph used to display data in polar plots.
Definition: qcustomplot.h:7599
QCPAxisTickerTime::tuMilliseconds
@ tuMilliseconds
Milliseconds, one thousandth of a second (%z in setTimeFormat)
Definition: qcustomplot.h:1820
QCPSelectionRect
Provides rect/rubber-band data selection and range zoom interaction.
Definition: qcustomplot.h:1118
QCPItemText::mainColor
QColor mainColor() const
Definition: qcustomplot.cpp:29878
QCPColorGradient::setColorStops
void setColorStops(const QMap< double, QColor > &colorStops)
Definition: qcustomplot.cpp:16597
QCustomPlot::paintEvent
virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15466
QCPColorMapData::setSize
void setSize(int keySize, int valueSize)
Definition: qcustomplot.cpp:25923
QCPScatterStyle::setPixmap
void setPixmap(const QPixmap &pixmap)
Definition: qcustomplot.cpp:10824
QCPPolarAxisAngular::setSubTickLength
void setSubTickLength(int inside, int outside=0)
Definition: qcustomplot.cpp:33598
QCPColorScaleAxisRectPrivate::axisSelectionChanged
Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts)
Definition: qcustomplot.cpp:20655
QCPPolarGraph::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged)
Definition: qcustomplot.cpp:35045
QCPPolarAxisRadial::getPartAt
SelectablePart getPartAt(const QPointF &pos) const
Definition: qcustomplot.cpp:32077
QCPVector2D::normalized
QCPVector2D normalized() const
Definition: qcustomplot.cpp:176
QCPGraph::addData
void addData(const QVector< double > &keys, const QVector< double > &values, bool alreadySorted=false)
Definition: qcustomplot.cpp:21034
QCustomPlot::createPaintBuffer
QCPAbstractPaintBuffer * createPaintBuffer()
Definition: qcustomplot.cpp:15866
QCustomPlot::drawBackground
void drawBackground(QCPPainter *painter)
Definition: qcustomplot.cpp:15779
QCPAxisPainterPrivate::viewportRect
QRect viewportRect
Definition: qcustomplot.h:2421
QCPLabelPainterPrivate::CachedLabel::pixmap
QPixmap pixmap
Definition: qcustomplot.h:1637
QCPItemStraightLine::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:28861
QCPErrorBars::mDataPlottable
QPointer< QCPAbstractPlottable > mDataPlottable
Definition: qcustomplot.h:6355
QCPAxis::mLabelFont
QFont mLabelFont
Definition: qcustomplot.h:2313
QCPAxisPainterPrivate::draw
virtual void draw(QCPPainter *painter)
Definition: qcustomplot.cpp:9930
QCPPainter::mAntialiasingStack
QStack< bool > mAntialiasingStack
Definition: qcustomplot.h:528
QCP::setMarginValue
void setMarginValue(QMargins &margins, QCP::MarginSide side, int value)
Definition: qcustomplot.h:348
QCPTextElement::text
QString text() const
Definition: qcustomplot.h:5251
QCPPolarGraph::clipRect
virtual QRect clipRect() const
Definition: qcustomplot.cpp:34927
QCPItemEllipse::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6729
QCPAxisRect::elements
virtual QList< QCPLayoutElement * > elements(bool recursive) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:17997
QCPPolarAxisRadial::LabelMode
LabelMode
Definition: qcustomplot.h:7005
QCPLayout::takeAt
virtual QCPLayoutElement * takeAt(int index)=0
QCustomPlot::deselectAll
Q_SLOT void deselectAll()
Definition: qcustomplot.cpp:15079
QCPPolarAxisRadial::AngleReference
AngleReference
Definition: qcustomplot.h:6980
QCPFinancial::twoColored
bool twoColored() const
Definition: qcustomplot.h:6196
QCPPolarAxisAngular::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:33018
QCPPolarAxisAngular::SelectablePart
SelectablePart
Definition: qcustomplot.h:7232
QCPPolarGraph::removeFromLegend
bool removeFromLegend() const
Definition: qcustomplot.cpp:34885
QCPPolarGraph::draw
virtual void draw(QCPPainter *painter)
Definition: qcustomplot.cpp:34935
QCPColorScale::mDataScaleType
QCPAxis::ScaleType mDataScaleType
Definition: qcustomplot.h:5397
QCPItemTracer::mGraph
QCPGraph * mGraph
Definition: qcustomplot.h:6883
QCPAbstractLegendItem::setSelectedTextColor
void setSelectedTextColor(const QColor &color)
Definition: qcustomplot.cpp:18784
QCPGraph::getScatters
void getScatters(QVector< QPointF > *scatters, const QCPDataRange &dataRange) const
Definition: qcustomplot.cpp:21270
QCPPolarGrid::drawRadialGrid
void drawRadialGrid(QCPPainter *painter, const QPointF &center, const QVector< double > &coords, const QPen &pen, const QPen &zeroPen=Qt::NoPen)
Definition: qcustomplot.cpp:34279
QCPPolarAxisAngular::coordToPixel
QPointF coordToPixel(double angleCoord, double radiusCoord) const
Definition: qcustomplot.cpp:32875
QCPLineEnding::draw
void draw(QCPPainter *painter, const QCPVector2D &pos, const QCPVector2D &dir) const
Definition: qcustomplot.cpp:5329
QCPPolarAxisAngular::setTickLabels
void setTickLabels(bool show)
Definition: qcustomplot.cpp:33373
QCPAxisRect::mRangeZoomVertAxis
QList< QPointer< QCPAxis > > mRangeZoomVertAxis
Definition: qcustomplot.h:4976
QCPPolarAxisRadial::getBasePen
QPen getBasePen() const
Definition: qcustomplot.cpp:32362
QCPAxisTickerText::mSubTickCount
int mSubTickCount
Definition: qcustomplot.h:1928
QCPLabelPainterPrivate::LabelData::suffixPart
QString suffixPart
Definition: qcustomplot.h:1644
QCP::iSelectLegend
@ iSelectLegend
0x020 Legends are selectable (or their child items, see QCPLegend::setSelectableParts)
Definition: qcustomplot.h:278
QCPAxisRect::mRangeZoomFactorHorz
double mRangeZoomFactorHorz
Definition: qcustomplot.h:4977
QCPLabelPainterPrivate::mAbbreviateDecimalPowers
bool mAbbreviateDecimalPowers
Definition: qcustomplot.h:1663
QCPAxisTickerDateTime::getTickStep
virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:6644
QCPItemTracer::tsPlus
@ tsPlus
A plus shaped crosshair with limited size.
Definition: qcustomplot.h:6837
QCPPolarAxisAngular::setTickLabelMode
void setTickLabelMode(LabelMode mode)
Definition: qcustomplot.cpp:33427
QCPAxis::mNumberFormatChar
QLatin1Char mNumberFormatChar
Definition: qcustomplot.h:2322
QCPErrorBars::setData
void setData(QSharedPointer< QCPErrorBarsDataContainer > data)
Definition: qcustomplot.cpp:27992
QCPDataSelection::contains
bool contains(const QCPDataSelection &other) const
Definition: qcustomplot.cpp:2684
QCPVector2D::toPoint
QPoint toPoint() const
Definition: qcustomplot.h:427
QCPPolarGrid::setAngularSubGridPen
void setAngularSubGridPen(const QPen &pen)
Definition: qcustomplot.cpp:34212
QCPColorMapData::setValueSize
void setValueSize(int valueSize)
Definition: qcustomplot.cpp:25979
QCPScatterStyle::setFromOther
void setFromOther(const QCPScatterStyle &other, ScatterProperties properties)
Definition: qcustomplot.cpp:10746
QCPPolarAxisAngular::mTicks
bool mTicks
Definition: qcustomplot.h:7429
QCPGraph::dataToStepLeftLines
QVector< QPointF > dataToStepLeftLines(const QVector< QCPGraphData > &data) const
Definition: qcustomplot.cpp:21363
QCPAxisTickerText::getTickLabel
virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7366
QCPItemPixmap::mTransformationMode
Qt::TransformationMode mTransformationMode
Definition: qcustomplot.h:6797
QCPAbstractLegendItem::setSelectedFont
void setSelectedFont(const QFont &font)
Definition: qcustomplot.cpp:18773
QCPAxis::pixelOrientation
int pixelOrientation() const
Definition: qcustomplot.h:2275
QCPItemPosition::coords
QPointF coords() const
Definition: qcustomplot.h:3639
QCPPlottableLegendItem::mPlottable
QCPAbstractPlottable * mPlottable
Definition: qcustomplot.h:5088
QCPAxis::mTicker
QSharedPointer< QCPAxisTicker > mTicker
Definition: qcustomplot.h:2339
QCPAbstractLegendItem::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18835
QCPAxisTickerTime::mBiggestUnit
TimeUnit mBiggestUnit
Definition: qcustomplot.h:1844
QCustomPlot::selectedLegends
QList< QCPLegend * > selectedLegends() const
Definition: qcustomplot.cpp:15043
QCPLayoutGrid::rowColToIndex
int rowColToIndex(int row, int column) const
Definition: qcustomplot.cpp:4524
QCPVector2D::operator/=
QCPVector2D & operator/=(double divisor)
Definition: qcustomplot.cpp:245
QCPBars::mWidth
double mWidth
Definition: qcustomplot.h:5838
QCPItemPosition::ptAbsolute
@ ptAbsolute
Static positioning in pixels, starting from the top left corner of the viewport/widget.
Definition: qcustomplot.h:3616
QCPAxisPainterPrivate::clearCache
void clearCache()
Definition: qcustomplot.cpp:10169
QCPPolarGrid::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:34245
QCPPolarAxisAngular::spAxis
@ spAxis
The axis backbone and tick marks.
Definition: qcustomplot.h:7233
QCPBarsGroup::keyPixelOffset
double keyPixelOffset(const QCPBars *bars, double keyCoord)
Definition: qcustomplot.cpp:24153
QCPLayer::mParentPlot
QCustomPlot * mParentPlot
Definition: qcustomplot.h:692
QCPItemTracer::mSize
double mSize
Definition: qcustomplot.h:6881
QCustomPlot::yAxis2
QCPAxis * yAxis2
Definition: qcustomplot.h:3907
QCPDataSelection::enforceType
void enforceType(QCP::SelectionType type)
Definition: qcustomplot.cpp:2637
QCPLayerable::parentPlotInitialized
virtual void parentPlotInitialized(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:1624
QCustomPlot::mPlotLayout
QCPLayoutGrid * mPlotLayout
Definition: qcustomplot.h:3935
QCPFinancial::mPenPositive
QPen mPenPositive
Definition: qcustomplot.h:6234
QCPPolarLegendItem::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:34336
QCPColorMap::mDataRange
QCPRange mDataRange
Definition: qcustomplot.h:6091
QCPPolarAxisAngular::rescale
void rescale(bool onlyVisiblePlottables=false)
Definition: qcustomplot.cpp:32826
QCPLegend::setFont
void setFont(const QFont &font)
Definition: qcustomplot.cpp:19132
QCPGraph::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:21073
QCPPolarAxisAngular::setRangeLower
void setRangeLower(double lower)
Definition: qcustomplot.cpp:33283
QCPStatisticalBox::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:25637
QCustomPlot::moveLayer
bool moveLayer(QCPLayer *layer, QCPLayer *otherLayer, LayerInsertMode insertMode=limAbove)
Definition: qcustomplot.cpp:14844
QCPItemText::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29749
QCPPolarGraph::setSelectable
Q_SLOT void setSelectable(QCP::SelectionType selectable)
Definition: qcustomplot.cpp:34565
QCPColorScale::gradientChanged
void gradientChanged(const QCPColorGradient &newGradient)
Definition: moc_qcustomplot.cpp:5434
QCPLabelPainterPrivate::SymbolCross
static const QChar SymbolCross
Definition: qcustomplot.h:1631
QCPLegend::mSelectedParts
SelectableParts mSelectedParts
Definition: qcustomplot.h:5197
QCPFinancial::mWidthType
WidthType mWidthType
Definition: qcustomplot.h:6231
QCPLayoutInset::~QCPLayoutInset
virtual ~QCPLayoutInset() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4891
QCP::aeAll
@ aeAll
0xFFFF All elements
Definition: qcustomplot.h:246
QCPAxis::spTickLabels
@ spTickLabels
Tick labels (numbers) of this axis (as a whole, not individually)
Definition: qcustomplot.h:2169
QCPAxis::mSelectedLabelColor
QColor mSelectedLabelColor
Definition: qcustomplot.h:2314
QCPAbstractPlottable::mSelectable
QCP::SelectionType mSelectable
Definition: qcustomplot.h:3533
QCPColorGradient::operator==
bool operator==(const QCPColorGradient &other) const
Definition: qcustomplot.cpp:16556
QCPPolarGraph::drawPolyline
void drawPolyline(QCPPainter *painter, const QVector< QPointF > &lineData) const
Definition: qcustomplot.cpp:35225
QCPItemTracer::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30604
QCPItemRect::topLeft
QCPItemPosition *const topLeft
Definition: qcustomplot.h:6557
QCPPolarAxisAngular::setSubTickPen
void setSubTickPen(const QPen &pen)
Definition: qcustomplot.cpp:33659
QCPVector2D::perpendicular
QCPVector2D perpendicular() const
Definition: qcustomplot.h:433
QCPAbstractLegendItem::selectableChanged
void selectableChanged(bool selectable)
Definition: moc_qcustomplot.cpp:4443
QCustomPlot::hasInvalidatedPaintBuffers
bool hasInvalidatedPaintBuffers()
Definition: qcustomplot.cpp:15893
QCPAbstractItem::clipRect
virtual QRect clipRect() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:13091
QCPColorGradient::setPeriodic
void setPeriodic(bool enabled)
Definition: qcustomplot.cpp:16667
QCPPolarAxisAngular::setRange
Q_SLOT void setRange(const QCPRange &range)
Definition: qcustomplot.cpp:33180
QCPAxisPainterPrivate::lowerEnding
QCPLineEnding lowerEnding
Definition: qcustomplot.h:2407
QCPAxisPainterPrivate::tickLabelFont
QFont tickLabelFont
Definition: qcustomplot.h:2419
QCPPolarGraph::dataCount
virtual int dataCount() const
Definition: qcustomplot.cpp:35201
QCPPolarAxisAngular::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:33024
QCPColorScale::setType
void setType(QCPAxis::AxisType type)
Definition: qcustomplot.cpp:20173
QCPColorMap::dataScaleTypeChanged
void dataScaleTypeChanged(QCPAxis::ScaleType scaleType)
Definition: moc_qcustomplot.cpp:6449
QCPLayoutGrid::setColumnSpacing
void setColumnSpacing(int pixels)
Definition: qcustomplot.cpp:4340
QCPDataSelection::addDataRange
void addDataRange(const QCPDataRange &dataRange, bool simplify=true)
Definition: qcustomplot.cpp:2574
QCPAxisTicker::trimTicks
void trimTicks(const QCPRange &range, QVector< double > &ticks, bool keepOneOutlier) const
Definition: qcustomplot.cpp:6377
QCPSelectionDecoratorBracket::mBracketPen
QPen mBracketPen
Definition: qcustomplot.h:4866
QCPLabelPainterPrivate::LabelData::suffixBounds
QRect suffixBounds
Definition: qcustomplot.h:1645
QCPItemLine::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6461
QCPAxisRect::mRangeDrag
Qt::Orientations mRangeDrag
Definition: qcustomplot.h:4974
QCPLayoutGrid::mElements
QList< QList< QCPLayoutElement * > > mElements
Definition: qcustomplot.h:1420
QCPPolarAxisAngular::mBackgroundPixmap
QPixmap mBackgroundPixmap
Definition: qcustomplot.h:7400
QCPAxisTickerDateTime::setDateTimeSpec
void setDateTimeSpec(Qt::TimeSpec spec)
Definition: qcustomplot.cpp:6586
QCPLayoutGrid::mColumnStretchFactors
QList< double > mColumnStretchFactors
Definition: qcustomplot.h:1421
QCPErrorBars::getDataSegments
void getDataSegments(QList< QCPDataRange > &selectedSegments, QList< QCPDataRange > &unselectedSegments) const
Definition: qcustomplot.cpp:28745
QCPPolarAxisAngular::setRangeZoomFactor
void setRangeZoomFactor(double factor)
Definition: qcustomplot.cpp:33161
QCPColorMapData::mDataBounds
QCPRange mDataBounds
Definition: qcustomplot.h:6033
QCPAxisRect::mBackgroundBrush
QBrush mBackgroundBrush
Definition: qcustomplot.h:4968
QCPAxisRect::mNotAADragBackup
QCP::AntialiasedElements mNotAADragBackup
Definition: qcustomplot.h:4981
QCPBars::selectTestRect
virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24647
QCP::aeItems
@ aeItems
0x0040 Main lines of items
Definition: qcustomplot.h:241
QCPLayout::removeAt
bool removeAt(int index)
Definition: qcustomplot.cpp:3739
QCPItemStraightLine::QCPItemStraightLine
QCPItemStraightLine(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:28840
QCPItemPixmap::aspectRatioMode
Qt::AspectRatioMode aspectRatioMode() const
Definition: qcustomplot.h:6765
QCPPolarAxisRadial::setLabelPadding
void setLabelPadding(int padding)
Definition: qcustomplot.cpp:31792
QCPAxis::getLabelFont
QFont getLabelFont() const
Definition: qcustomplot.cpp:9785
QCPItemPixmap::aiBottom
@ aiBottom
Definition: qcustomplot.h:6789
QCPLineEnding::mWidth
double mWidth
Definition: qcustomplot.h:1545
QCPLayoutInset::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:5093
QCPLayoutGrid::elementAt
virtual QCPLayoutElement * elementAt(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4625
QCPItemRect::mainBrush
QBrush mainBrush() const
Definition: qcustomplot.cpp:29550
QCPPolarAxisAngular::selectableChanged
void selectableChanged(const QCPPolarAxisAngular::SelectableParts &parts)
Definition: moc_qcustomplot.cpp:8527
QCPSelectionDecoratorBracket::setBracketStyle
void setBracketStyle(BracketStyle style)
Definition: qcustomplot.cpp:17202
QCPLayout::adoptElement
void adoptElement(QCPLayoutElement *el)
Definition: qcustomplot.cpp:3831
QCPAxisPainterPrivate::TickLabelData::expPart
QString expPart
Definition: qcustomplot.h:2438
QCPAbstractItem::~QCPAbstractItem
virtual ~QCPAbstractItem() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:12943
QCPItemText::setSelectedBrush
void setSelectedBrush(const QBrush &brush)
Definition: qcustomplot.cpp:29669
QCPAxisPainterPrivate::labelSelectionBox
QRect labelSelectionBox() const
Definition: qcustomplot.h:2402
QCPPainter::QCPPainter
QCPPainter()
Definition: qcustomplot.cpp:297
QCPLayerable::mParentLayerable
QPointer< QCPLayerable > mParentLayerable
Definition: qcustomplot.h:756
QCP::msLeft
@ msLeft
0x01 left margin
Definition: qcustomplot.h:217
QCPPolarAxisAngular::mSelectableParts
SelectableParts mSelectableParts
Definition: qcustomplot.h:7411
QCPCurve::setScatterStyle
void setScatterStyle(const QCPScatterStyle &style)
Definition: qcustomplot.cpp:22698
QCPGrid::setAntialiasedSubGrid
void setAntialiasedSubGrid(bool enabled)
Definition: qcustomplot.cpp:7886
QCPLayerable::initializeParentPlot
void initializeParentPlot(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:1528
QCPItemRect::setSelectedBrush
void setSelectedBrush(const QBrush &brush)
Definition: qcustomplot.cpp:29482
QCPItemAnchor::QCPItemPosition
friend class QCPItemPosition
Definition: qcustomplot.h:3601
QCPAxisRect::removeAxis
bool removeAxis(QCPAxis *axis)
Definition: qcustomplot.cpp:17751
QCPScatterStyle::ssPeace
@ ssPeace
\enumimage{ssPeace.png} a circle, with one vertical and two downward diagonal lines
Definition: qcustomplot.h:2507
QCustomPlot::savePdf
bool savePdf(const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString())
Definition: qcustomplot.cpp:15234
QCPPolarAxisRadial::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32096
QCPLayoutGrid::columnCount
int columnCount() const
Definition: qcustomplot.h:1378
QCPFinancial::setBrushNegative
void setBrushNegative(const QBrush &brush)
Definition: qcustomplot.cpp:27188
QCPAxis::mSelectedTickLabelFont
QFont mSelectedTickLabelFont
Definition: qcustomplot.h:2319
QCPAxisTickerTime::replaceUnit
void replaceUnit(QString &text, TimeUnit unit, int value) const
Definition: qcustomplot.cpp:7071
QCPPolarAxisRadial::mLabelPadding
int mLabelPadding
Definition: qcustomplot.h:7141
QCPPolarAxisRadial::mRangeZoom
bool mRangeZoom
Definition: qcustomplot.h:7131
QCPAxisTickerTime::tuHours
@ tuHours
Hours (%h in setTimeFormat)
Definition: qcustomplot.h:1823
QCPDataRange::QCPDataRange
QCPDataRange()
Definition: qcustomplot.cpp:2257
QCPItemRect::anchorPixelPosition
virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29518
QCPAxisPainterPrivate::abbreviateDecimalPowers
bool abbreviateDecimalPowers
Definition: qcustomplot.h:2423
QCPItemLine::setTail
void setTail(const QCPLineEnding &tail)
Definition: qcustomplot.cpp:29080
QCustomPlot::selectionTolerance
int selectionTolerance() const
Definition: qcustomplot.h:3805
QCPItemCurve::endDir
QCPItemPosition *const endDir
Definition: qcustomplot.h:6508
QCPAbstractItem::mSelectable
bool mSelectable
Definition: qcustomplot.h:3721
QCPItemPosition::mValueAxis
QPointer< QCPAxis > mValueAxis
Definition: qcustomplot.h:3661
QCPBarsGroup::SpacingType
SpacingType
Definition: qcustomplot.h:5694
QCPColorMap::QCPColorMap
QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:26408
QCPAxisTickerPi::unicodeFraction
QString unicodeFraction(int numerator, int denominator) const
Definition: qcustomplot.cpp:7636
QCPPolarAxisRadial::~QCPPolarAxisRadial
virtual ~QCPPolarAxisRadial()
Definition: qcustomplot.cpp:31126
QCustomPlot::clearGraphs
int clearGraphs()
Definition: qcustomplot.cpp:14478
QCPLayoutGrid::minimumOuterSizeHint
virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4748
QCPLabelPainterPrivate::analyzeFontMetrics
void analyzeFontMetrics()
Definition: qcustomplot.cpp:6047
QCPRange::sanitizedForLogScale
QCPRange sanitizedForLogScale() const
Definition: qcustomplot.cpp:2065
QCPColorMapData::~QCPColorMapData
~QCPColorMapData()
Definition: qcustomplot.cpp:25827
QCPAxisRect::calculateAutoMargin
virtual int calculateAutoMargin(QCP::MarginSide side) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18473
QCPPolarGraph::lsLine
@ lsLine
data points are connected by a straight line
Definition: qcustomplot.h:7613
QCustomPlot::setBackgroundScaled
void setBackgroundScaled(bool scaled)
Definition: qcustomplot.cpp:14215
QCPAxis::stLogarithmic
@ stLogarithmic
Logarithmic scaling with correspondingly transformed axis coordinates (possibly also setTicker to a Q...
Definition: qcustomplot.h:2160
QCPSelectionRect::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:2967
QCPGrid::mAntialiasedZeroLine
bool mAntialiasedZeroLine
Definition: qcustomplot.h:2067
QCPAxisTickerPi::getTickLabel
virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7518
QCPGraph::getOptimizedLineData
virtual void getOptimizedLineData(QVector< QCPGraphData > *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const
Definition: qcustomplot.cpp:21661
QCPErrorBars::pointDistance
double pointDistance(const QPointF &pixelPoint, QCPErrorBarsDataContainer::const_iterator &closestData) const
Definition: qcustomplot.cpp:28705
QCPLayoutElement::minimumOuterSizeHint
virtual QSize minimumOuterSizeHint() const
Definition: qcustomplot.cpp:3477
QCPItemLine::setHead
void setHead(const QCPLineEnding &head)
Definition: qcustomplot.cpp:29067
QCustomPlot::layerableAt
QCPLayerable * layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails=nullptr) const
Definition: qcustomplot.cpp:16298
QCPPolarGraph::valueAxis
QCPPolarAxisRadial * valueAxis() const
Definition: qcustomplot.h:7628
QCPPolarAxisAngular::setSelectedTickLabelColor
void setSelectedTickLabelColor(const QColor &color)
Definition: qcustomplot.cpp:33745
QCPLegend::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19541
QCPAxis::pixelToCoord
double pixelToCoord(double value) const
Definition: qcustomplot.cpp:9261
QCPAxisRect::axes
QList< QCPAxis * > axes() const
Definition: qcustomplot.cpp:17643
QCPLineEnding::esHalfBar
@ esHalfBar
A bar perpendicular to the line, pointing out to only one side (to which side can be changed with set...
Definition: qcustomplot.h:1516
QCPItemLine::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:29054
QCPColorMap::dataRange
QCPRange dataRange() const
Definition: qcustomplot.h:6059
QCPAxis::axisType
AxisType axisType() const
Definition: qcustomplot.h:2180
QCPPolarGraph::setSelection
Q_SLOT void setSelection(QCPDataSelection selection)
Definition: qcustomplot.cpp:34599
QCPCurve::drawScatterPlot
virtual void drawScatterPlot(QCPPainter *painter, const QVector< QPointF > &points, const QCPScatterStyle &style) const
Definition: qcustomplot.cpp:22995
QCPLayoutGrid::expandTo
void expandTo(int newRowCount, int newColumnCount)
Definition: qcustomplot.cpp:4441
QCPBars::getPixelWidth
void getPixelWidth(double key, double &lower, double &upper) const
Definition: qcustomplot.cpp:24978
QCPLayoutGrid::rowCount
int rowCount() const
Definition: qcustomplot.h:1377
QCPLegend::mIconSize
QSize mIconSize
Definition: qcustomplot.h:5195
QCPBars::mStackingGap
double mStackingGap
Definition: qcustomplot.h:5842
QCPColorMapData::mIsEmpty
bool mIsEmpty
Definition: qcustomplot.h:6028
QCPLabelPainterPrivate::LabelData::basePart
QString basePart
Definition: qcustomplot.h:1644
QCPPolarGraph::mSelection
QCPDataSelection mSelection
Definition: qcustomplot.h:7693
QCPItemEllipse::center
QCPItemAnchor *const center
Definition: qcustomplot.h:6723
QCPAxis::mAxisRect
QCPAxisRect * mAxisRect
Definition: qcustomplot.h:2303
QCPAxisTicker::getSubTickCount
virtual int getSubTickCount(double tickStep)
Definition: qcustomplot.cpp:6230
QCPItemCurve::~QCPItemCurve
virtual ~QCPItemCurve() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29277
QCPSelectionDecorator::applyPen
void applyPen(QCPPainter *painter) const
Definition: qcustomplot.cpp:11114
QCPFinancial::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27447
QCPAxisTickerText::QCPAxisTickerText
QCPAxisTickerText()
Definition: qcustomplot.cpp:7227
QCPPolarAxisRadial::mNumberBeautifulPowers
bool mNumberBeautifulPowers
Definition: qcustomplot.h:7153
QCPPolarAxisRadial::setTickLabelColor
void setTickLabelColor(const QColor &color)
Definition: qcustomplot.cpp:31494
QCPFinancial::wtPlotCoords
@ wtPlotCoords
width is in key coordinates and thus scales with the key axis range
Definition: qcustomplot.h:6174
QCPPolarAxisAngular::getTickLabelFont
QFont getTickLabelFont() const
Definition: qcustomplot.cpp:33909
QCPAbstractPaintBuffer::~QCPAbstractPaintBuffer
virtual ~QCPAbstractPaintBuffer()
Definition: qcustomplot.cpp:588
QCPBars::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24856
QCPLayoutElement::setMargins
void setMargins(const QMargins &margins)
Definition: qcustomplot.cpp:3260
QCPBars::setStackingGap
void setStackingGap(double pixels)
Definition: qcustomplot.cpp:24531
QCPAxis::subTicks
bool subTicks() const
Definition: qcustomplot.h:2199
QCPCurve::setLineStyle
void setLineStyle(LineStyle style)
Definition: qcustomplot.cpp:22726
QCP::aeLegend
@ aeLegend
0x0008 Legend box
Definition: qcustomplot.h:238
QCPPolarAxisRadial::setAngleReference
void setAngleReference(AngleReference reference)
Definition: qcustomplot.cpp:31408
QCPAxis::setRangeReversed
void setRangeReversed(bool reversed)
Definition: qcustomplot.cpp:8549
QCPAxis::setTicker
void setTicker(QSharedPointer< QCPAxisTicker > ticker)
Definition: qcustomplot.cpp:8567
QCPLayoutGrid::setRowStretchFactor
void setRowStretchFactor(int row, double factor)
Definition: qcustomplot.cpp:4294
QCPLabelPainterPrivate::clearCache
void clearCache()
Definition: qcustomplot.cpp:5639
QCPAxisTickerPi::getTickStep
virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7490
QCPAxis::mSubTickPen
QPen mSubTickPen
Definition: qcustomplot.h:2330
QCPItemText::setSelectedColor
void setSelectedColor(const QColor &color)
Definition: qcustomplot.cpp:29625
QCustomPlot::axisDoubleClick
void axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3888
QCPItemCurve::end
QCPItemPosition *const end
Definition: qcustomplot.h:6509
QCPLabelPainterPrivate::CachedLabel::offset
QPoint offset
Definition: qcustomplot.h:1636
QCPItemPosition
Manages the position of an item.
Definition: qcustomplot.h:3606
QCPItemText::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:29636
QCPPolarGraph::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:34513
QCPLabelPainterPrivate::cacheKey
QByteArray cacheKey(const QString &text, const QColor &color, double rotation, AnchorSide side) const
Definition: qcustomplot.cpp:5984
QCPPolarAxisAngular::elements
virtual QList< QCPLayoutElement * > elements(bool recursive) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32989
QCPPolarAxisAngular::setLabelColor
void setLabelColor(const QColor &color)
Definition: qcustomplot.cpp:33683
QCPRange::bounded
QCPRange bounded(double lowerBound, double upperBound) const
Definition: qcustomplot.cpp:2030
QCPItemAnchor::toQCPItemPosition
virtual QCPItemPosition * toQCPItemPosition()
Definition: qcustomplot.h:3590
QCP::ResolutionUnit
ResolutionUnit
Definition: qcustomplot.h:186
QCPPolarAxisAngular::mRadius
double mRadius
Definition: qcustomplot.h:7440
QCPBarsGroup
Groups multiple QCPBars together so they appear side by side.
Definition: qcustomplot.h:5680
QCPDataSelection::span
QCPDataRange span() const
Definition: qcustomplot.cpp:2560
QCPAxisTickerLog::setSubTickCount
void setSubTickCount(int subTicks)
Definition: qcustomplot.cpp:7755
QCPErrorBars::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28480
QCPColorScale::type
QCPAxis::AxisType type() const
Definition: qcustomplot.h:5362
QCPAbstractItem::mClipAxisRect
QPointer< QCPAxisRect > mClipAxisRect
Definition: qcustomplot.h:3718
QCPItemTracer::setSelectedBrush
void setSelectedBrush(const QBrush &brush)
Definition: qcustomplot.cpp:30463
QCPPolarGraph::selected
bool selected() const
Definition: qcustomplot.h:7630
QCPLayoutInset::insetAlignment
Qt::Alignment insetAlignment(int index) const
Definition: qcustomplot.cpp:4916
QCustomPlot::mouseRelease
void mouseRelease(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3839
QCPSelectionRect::~QCPSelectionRect
virtual ~QCPSelectionRect() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:2854
QCPAxis::mBasePen
QPen mBasePen
Definition: qcustomplot.h:2308
QCPLineEnding::realLength
double realLength() const
Definition: qcustomplot.cpp:5299
QCustomPlot::mNoAntialiasingOnDrag
bool mNoAntialiasingOnDrag
Definition: qcustomplot.h:3944
QCPPolarAxisRadial
The radial axis inside a radial plot.
Definition: qcustomplot.h:6970
QCPPolarAxisRadial::wheelEvent
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32247
QCPAxisTickerDateTime::dsUniformDayInMonth
@ dsUniformDayInMonth
Definition: qcustomplot.h:1796
QCPAxisTicker::QCPAxisTicker
QCPAxisTicker()
Definition: qcustomplot.cpp:6119
QCPItemCurve::mHead
QCPLineEnding mHead
Definition: qcustomplot.h:6514
QCPAbstractPlottable::mKeyAxis
QPointer< QCPAxis > mKeyAxis
Definition: qcustomplot.h:3532
QCPPainter::PainterMode
PainterMode
Definition: qcustomplot.h:488
QCPItemStraightLine::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6412
QCPPolarAxisRadial::mNumberPrecision
int mNumberPrecision
Definition: qcustomplot.h:7151
QCustomPlot::mouseWheel
void mouseWheel(QWheelEvent *event)
Definition: moc_qcustomplot.cpp:3846
QCPPolarGraph::selection
QCPDataSelection selection() const
Definition: qcustomplot.h:7631
QCPAxisTickerText::getSubTickCount
virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7354
QCPPolarAxisAngular::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:34037
QCPAxisTickerDateTime::mDateTimeFormat
QString mDateTimeFormat
Definition: qcustomplot.h:1790
QCPLayoutInset::mInsetPlacement
QList< InsetPlacement > mInsetPlacement
Definition: qcustomplot.h:1478
QCPPolarAxisRadial::mRangeDrag
bool mRangeDrag
Definition: qcustomplot.h:7130
QCPBarsGroup::remove
void remove(QCPBars *bars)
Definition: qcustomplot.cpp:24108
QCPAxis::setUpperEnding
void setUpperEnding(const QCPLineEnding &ending)
Definition: qcustomplot.cpp:9099
QCustomPlot::saveBmp
bool saveBmp(const QString &fileName, int width=0, int height=0, double scale=1.0, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
Definition: qcustomplot.cpp:15433
QCPDataRange::begin
int begin() const
Definition: qcustomplot.h:924
QCPBars::setWidth
void setWidth(double width)
Definition: qcustomplot.cpp:24474
QCPStatisticalBox::setWhiskerAntialiased
void setWhiskerAntialiased(bool enabled)
Definition: qcustomplot.cpp:25402
QCPBarsGroup::mSpacing
double mSpacing
Definition: qcustomplot.h:5726
QCPColorGradient::gpIon
@ gpIon
Half hue spectrum from black over purple to blue and finally green (creates banding illusion but allo...
Definition: qcustomplot.h:4752
QCustomPlot::plottingHints
QCP::PlottingHints plottingHints() const
Definition: qcustomplot.h:3807
QCPRange::QCPRange
QCPRange()
Definition: qcustomplot.cpp:1927
QCustomPlot::noAntialiasingOnDrag
bool noAntialiasingOnDrag() const
Definition: qcustomplot.h:3806
QCPPolarAxisAngular::size
QSize size() const
Definition: qcustomplot.h:7383
QCPAxisPainterPrivate::numberMultiplyCross
bool numberMultiplyCross
Definition: qcustomplot.h:2416
QCustomPlot::mPlottingHints
QCP::PlottingHints mPlottingHints
Definition: qcustomplot.h:3951
QCPAxis::subTickLengthOut
int subTickLengthOut() const
Definition: qcustomplot.cpp:8322
QCPAxisTickerTime::mSmallestUnit
TimeUnit mSmallestUnit
Definition: qcustomplot.h:1844
QCPAxis::LabelSide
LabelSide
Definition: qcustomplot.h:2151
QCustomPlot::removeLayer
bool removeLayer(QCPLayer *layer)
Definition: qcustomplot.cpp:14797
QCPAbstractPlottable::setSelection
Q_SLOT void setSelection(QCPDataSelection selection)
Definition: qcustomplot.cpp:11553
QCPLayoutElement::mRect
QRect mRect
Definition: qcustomplot.h:1282
QCPPolarAxisAngular::mTickVector
QVector< double > mTickVector
Definition: qcustomplot.h:7445
QCPAxisRect::top
int top() const
Definition: qcustomplot.h:4951
QCPPolarAxisAngular::angleRadToCoord
double angleRadToCoord(double angleRad) const
Definition: qcustomplot.h:7371
QCustomPlot::mOpenGlAntialiasedElementsBackup
QCP::AntialiasedElements mOpenGlAntialiasedElementsBackup
Definition: qcustomplot.h:3969
QCPColorGradient::nhHighestColor
@ nhHighestColor
NaN data points appear as the highest color defined in this QCPColorGradient.
Definition: qcustomplot.h:4736
QCPColorGradient::colorStops
QMap< double, QColor > colorStops() const
Definition: qcustomplot.h:4768
QCPAxis::tickLengthIn
int tickLengthIn() const
Definition: qcustomplot.cpp:8304
QCPItemBracket::anchorPixelPosition
virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30943
QCPTextElement::mText
QString mText
Definition: qcustomplot.h:5284
QCPAbstractPlottable::removeFromLegend
bool removeFromLegend() const
Definition: qcustomplot.cpp:11871
QCustomPlot::setupOpenGl
bool setupOpenGl()
Definition: qcustomplot.cpp:15916
QCPPolarAxisRadial::rangeChanged
void rangeChanged(const QCPRange &newRange)
Definition: moc_qcustomplot.cpp:8279
QCPLegend::item
QCPAbstractLegendItem * item(int index) const
Definition: qcustomplot.cpp:19338
QCPLegend::iconTextPadding
int iconTextPadding() const
Definition: qcustomplot.h:5143
QCPPolarAxisRadial::coordToRadius
double coordToRadius(double coord) const
Definition: qcustomplot.cpp:32026
QCPPolarGrid::mSubGridType
GridTypes mSubGridType
Definition: qcustomplot.h:7542
QCPLabelPainterPrivate::setFont
void setFont(const QFont &font)
Definition: qcustomplot.cpp:5524
QCustomPlot::mMouseEventLayerableDetails
QVariant mMouseEventLayerableDetails
Definition: qcustomplot.h:3963
QCPItemCurve::start
QCPItemPosition *const start
Definition: qcustomplot.h:6506
QCustomPlot::rpQueuedRefresh
@ rpQueuedRefresh
Replots immediately, but queues the widget repaint, by calling QWidget::update() after the replot....
Definition: qcustomplot.h:3785
QCPAxisPainterPrivate::QCPAxisPainterPrivate
QCPAxisPainterPrivate(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:9894
QCPColorGradient::mLevelCount
int mLevelCount
Definition: qcustomplot.h:4793
QCPLabelPainterPrivate::CachedLabel
Definition: qcustomplot.h:1634
QCPPolarAxisAngular::mNumberBeautifulPowers
bool mNumberBeautifulPowers
Definition: qcustomplot.h:7426
QCPTextElement::setSelectedTextColor
void setSelectedTextColor(const QColor &color)
Definition: qcustomplot.cpp:19843
QCPAxisRect::mRangeDragVertAxis
QList< QPointer< QCPAxis > > mRangeDragVertAxis
Definition: qcustomplot.h:4975
QCPLayoutElement::upMargins
@ upMargins
Phase in which the margins are calculated and set.
Definition: qcustomplot.h:1222
QCPColorMap::setData
void setData(QCPColorMapData *data, bool copy=false)
Definition: qcustomplot.cpp:26431
QCPCurve::data
QSharedPointer< QCPCurveDataContainer > data() const
Definition: qcustomplot.h:5620
QCPAxis::mNumberBeautifulPowers
bool mNumberBeautifulPowers
Definition: qcustomplot.h:2323
QCPSelectionDecoratorBracket::bsSquareBracket
@ bsSquareBracket
A square bracket is drawn.
Definition: qcustomplot.h:4829
QCPAxis::mDragging
bool mDragging
Definition: qcustomplot.h:2345
QCPItemLine::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:29224
QCPScatterStyle::mPenDefined
bool mPenDefined
Definition: qcustomplot.h:2556
QCPItemRect::~QCPItemRect
virtual ~QCPItemRect() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29441
QCPScatterStyle::isPenDefined
bool isPenDefined() const
Definition: qcustomplot.h:2540
QCPLabelPainterPrivate::mMultiplicationSymbol
QChar mMultiplicationSymbol
Definition: qcustomplot.h:1662
QCPPolarAxisRadial::rescale
void rescale(bool onlyVisiblePlottables=false)
Definition: qcustomplot.cpp:31957
QCPScatterStyle::mCustomPath
QPainterPath mCustomPath
Definition: qcustomplot.h:2553
QCPAxisTickerPi::setPeriodicity
void setPeriodicity(int multiplesOfPi)
Definition: qcustomplot.cpp:7468
QCPColorScale::rangeDrag
bool rangeDrag() const
Definition: qcustomplot.cpp:20139
QCPColorMap::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:26677
QCPAbstractPlottable::selectable
QCP::SelectionType selectable() const
Definition: qcustomplot.h:3485
QCPLayoutGrid::take
virtual bool take(QCPLayoutElement *element) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4661
QCPAbstractPlottable::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:11889
QCPScatterStyle::brush
QBrush brush() const
Definition: qcustomplot.h:2525
QCPAbstractPaintBuffer::mDevicePixelRatio
double mDevicePixelRatio
Definition: qcustomplot.h:564
QCPGraph::drawImpulsePlot
virtual void drawImpulsePlot(QCPPainter *painter, const QVector< QPointF > &lines) const
Definition: qcustomplot.cpp:21635
QCPPolarAxisRadial::mTickVector
QVector< double > mTickVector
Definition: qcustomplot.h:7170
QCPPolarAxisAngular::setTickPen
void setTickPen(const QPen &pen)
Definition: qcustomplot.cpp:33649
QCPPolarAxisAngular::mLabelPadding
int mLabelPadding
Definition: qcustomplot.h:7414
QCPPolarAxisAngular::setRangeReversed
void setRangeReversed(bool reversed)
Definition: qcustomplot.cpp:33320
QCPAxis::rangeChanged
void rangeChanged(const QCPRange &newRange)
Definition: moc_qcustomplot.cpp:2472
QCPAxisTickerFixed::setScaleStrategy
void setScaleStrategy(ScaleStrategy strategy)
Definition: qcustomplot.cpp:7142
QCPItemTracer::size
double size() const
Definition: qcustomplot.h:6852
QCPRange::sanitizedForLinScale
QCPRange sanitizedForLinScale() const
Definition: qcustomplot.cpp:2114
QCPAbstractPlottable::setValueAxis
void setValueAxis(QCPAxis *axis)
Definition: qcustomplot.cpp:11529
QCPItemText::setRotation
void setRotation(double degrees)
Definition: qcustomplot.cpp:29734
color
GLfloat color[8][3]
Definition: model.hh:19
QCPFinancial::setWidth
void setWidth(double width)
Definition: qcustomplot.cpp:27133
QCPColorMapData::operator=
QCPColorMapData & operator=(const QCPColorMapData &other)
Definition: qcustomplot.cpp:25851
QCPLabelPainterPrivate::mParentPlot
QCustomPlot * mParentPlot
Definition: qcustomplot.h:1665
QCPPolarAxisRadial::setTickLengthOut
void setTickLengthOut(int outside)
Definition: qcustomplot.cpp:31651
QCPGraphData::QCPGraphData
QCPGraphData()
Definition: qcustomplot.cpp:20779
QCPFinancial::ChartStyle
ChartStyle
Definition: qcustomplot.h:6183
QCPAxisPainterPrivate::offset
int offset
Definition: qcustomplot.h:2422
QCPSelectionDecorator::setUsedScatterProperties
void setUsedScatterProperties(const QCPScatterStyle::ScatterProperties &properties)
Definition: qcustomplot.cpp:11104
QCPColorScaleAxisRectPrivate::mGradientImage
QImage mGradientImage
Definition: qcustomplot.h:5326
QCPLayerable::mParentPlot
QCustomPlot * mParentPlot
Definition: qcustomplot.h:755
QCPVector2D::y
double y() const
Definition: qcustomplot.h:415
QCPLegend::setIconBorderPen
void setIconBorderPen(const QPen &pen)
Definition: qcustomplot.cpp:19194
QCPAxisTicker::createSubTickVector
virtual QVector< double > createSubTickVector(int subTickCount, const QVector< double > &ticks)
Definition: qcustomplot.cpp:6307
QCPAbstractPlottable::addToLegend
bool addToLegend()
Definition: qcustomplot.cpp:11833
QCPAxisRect::mBackgroundScaledMode
Qt::AspectRatioMode mBackgroundScaledMode
Definition: qcustomplot.h:4972
QCPItemEllipse::mBrush
QBrush mBrush
Definition: qcustomplot.h:6730
QCPAxisTickerTime::QCPAxisTickerTime
QCPAxisTickerTime()
Definition: qcustomplot.cpp:6879
QCPAxis::setSelectedTickLabelFont
void setSelectedTickLabelFont(const QFont &font)
Definition: qcustomplot.cpp:9001
QCPLayer::visible
bool visible() const
Definition: qcustomplot.h:680
QCPAxis::setOffset
void setOffset(int offset)
Definition: qcustomplot.cpp:8991
QCPItemTracer::style
TracerStyle style() const
Definition: qcustomplot.h:6853
QCPItemText::mPen
QPen mPen
Definition: qcustomplot.h:6658
QCPCurveData::QCPCurveData
QCPCurveData()
Definition: qcustomplot.cpp:22539
QCP::phImmediateRefresh
@ phImmediateRefresh
Definition: qcustomplot.h:259
QCPBarsGroup::setSpacingType
void setSpacingType(SpacingType spacingType)
Definition: qcustomplot.cpp:24013
QCPPolarAxisRadial::mTicker
QSharedPointer< QCPAxisTicker > mTicker
Definition: qcustomplot.h:7169
QCustomPlot::notAntialiasedElements
QCP::AntialiasedElements notAntialiasedElements() const
Definition: qcustomplot.h:3802
QCPBarsGroup::stPlotCoords
@ stPlotCoords
Bar spacing is in key coordinates and thus scales with the key axis range.
Definition: qcustomplot.h:5696
QCPLayoutGrid
A layout that arranges child elements in a grid.
Definition: qcustomplot.h:1346
QCPLabelPainterPrivate::setAnchorReferenceType
void setAnchorReferenceType(AnchorReferenceType type)
Definition: qcustomplot.cpp:5519
QCPErrorBars::getVisibleDataBounds
void getVisibleDataBounds(QCPErrorBarsDataContainer::const_iterator &begin, QCPErrorBarsDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const
Definition: qcustomplot.cpp:28646
QCPLayoutGrid::elementCount
virtual int elementCount() const Q_DECL_OVERRIDE
Definition: qcustomplot.h:1398
QCPPolarAxisAngular::rangeChanged
void rangeChanged(const QCPRange &newRange)
Definition: moc_qcustomplot.cpp:8506
QCPLayout::getFinalMaximumOuterSize
static QSize getFinalMaximumOuterSize(const QCPLayoutElement *el)
Definition: qcustomplot.cpp:4045
QCPItemStraightLine::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:28871
QCPPolarAxisRadial::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32123
QCPColorMapData::mValueSize
int mValueSize
Definition: qcustomplot.h:6026
QCPPaintBufferPixmap::reallocateBuffer
virtual void reallocateBuffer() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:703
QCustomPlot::viewport
QRect viewport() const
Definition: qcustomplot.h:3795
QCPLegend::clearItems
void clearItems()
Definition: qcustomplot.cpp:19466
QCPLineEnding::esDiamond
@ esDiamond
A filled diamond (45 degrees rotated square)
Definition: qcustomplot.h:1514
QCPLayer::mPaintBuffer
QWeakPointer< QCPAbstractPaintBuffer > mPaintBuffer
Definition: qcustomplot.h:700
QCPAxis::setBasePen
void setBasePen(const QPen &pen)
Definition: qcustomplot.cpp:8888
QCPScatterStyle::ssCustom
@ ssCustom
custom painter operations are performed per scatter (As QPainterPath, see setCustomPath)
Definition: qcustomplot.h:2509
QCPPolarAxisRadial::setSelectedLabelColor
void setSelectedLabelColor(const QColor &color)
Definition: qcustomplot.cpp:31844
QCPStatisticalBox::mWhiskerBarPen
QPen mWhiskerBarPen
Definition: qcustomplot.h:5957
QCPAbstractLegendItem::QCPAbstractLegendItem
QCPAbstractLegendItem(QCPLegend *parent)
Definition: qcustomplot.cpp:18733
QCustomPlot::mReplotQueued
bool mReplotQueued
Definition: qcustomplot.h:3966
QCPScatterStyle::size
double size() const
Definition: qcustomplot.h:2522
QCPTextElement::minimumOuterSizeHint
virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19894
QCPPolarGraph::setValueAxis
void setValueAxis(QCPPolarAxisRadial *axis)
Definition: qcustomplot.cpp:34550
QCPPolarAxisAngular::tickLabelMode
LabelMode tickLabelMode() const
Definition: qcustomplot.cpp:32634
QCPPlottableLegendItem::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18950
QCPSelectionDecoratorBracket::setBracketBrush
void setBracketBrush(const QBrush &brush)
Definition: qcustomplot.cpp:17172
QCPLabelPainterPrivate::generateLabelParameterHash
virtual QByteArray generateLabelParameterHash() const
Definition: qcustomplot.cpp:5651
QCPLayoutElement::maximumOuterSizeHint
virtual QSize maximumOuterSizeHint() const
Definition: qcustomplot.cpp:3496
QCPLayoutElement::layout
QCPLayout * layout() const
Definition: qcustomplot.h:1244
QCPLineEnding::setLength
void setLength(double length)
Definition: qcustomplot.cpp:5237
QCPLayoutGrid::insertRow
void insertRow(int newIndex)
Definition: qcustomplot.cpp:4466
QCPItemRect::brush
QBrush brush() const
Definition: qcustomplot.h:6545
QCPPolarAxisAngular::mNotAADragBackup
QCP::AntialiasedElements mNotAADragBackup
Definition: qcustomplot.h:7453
QCPBars::moveAbove
void moveAbove(QCPBars *bars)
Definition: qcustomplot.cpp:24625
QCPItemStraightLine::~QCPItemStraightLine
virtual ~QCPItemStraightLine() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28852
QCPPlottableLegendItem::getIconBorderPen
QPen getIconBorderPen() const
Definition: qcustomplot.cpp:18919
QCPLayoutInset::addElement
void addElement(QCPLayoutElement *element, Qt::Alignment alignment)
Definition: qcustomplot.cpp:5120
QCPBarsGroup::getPixelSpacing
double getPixelSpacing(const QCPBars *bars, double keyCoord)
Definition: qcustomplot.cpp:24219
QCPColorGradient::clearColorStops
void clearColorStops()
Definition: qcustomplot.cpp:16968
QCPItemRect::mPen
QPen mPen
Definition: qcustomplot.h:6570
QCPBars::moveBelow
void moveBelow(QCPBars *bars)
Definition: qcustomplot.cpp:24592
QCPVector2D::dot
double dot(const QCPVector2D &vec) const
Definition: qcustomplot.h:434
QCPItemPosition::setParentAnchorX
bool setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false)
Definition: qcustomplot.cpp:12374
QCPLayoutElement::mAutoMargins
QCP::MarginSides mAutoMargins
Definition: qcustomplot.h:1284
QCPAxis::mSubTickVector
QVector< double > mSubTickVector
Definition: qcustomplot.h:2342
QCPSelectionRect::accepted
void accepted(const QRect &rect, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:857
QCPPolarAxisAngular::LabelMode
LabelMode
Definition: qcustomplot.h:7244
QCPPolarGraph::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
Definition: qcustomplot.cpp:35110
QCPAxisTickerDateTime::getTickLabel
virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:6714
QCPPolarAxisAngular::getLabelFont
QFont getLabelFont() const
Definition: qcustomplot.cpp:33919
QCPStatisticalBox::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:25579
QCPBarsGroup::setSpacing
void setSpacing(double spacing)
Definition: qcustomplot.cpp:24024
QCPLegend::QCPLegend
QCPLegend()
Definition: qcustomplot.cpp:19054
QCPLayout::update
virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:3679
QCPRange::validRange
static bool validRange(double lower, double upper)
Definition: qcustomplot.cpp:2129
QCPColorGradient::gpJet
@ gpJet
Hue variation similar to a spectrum, often used in numerical visualization (creates banding illusion ...
Definition: qcustomplot.h:4756
QCPMarginGroup::addChild
void addChild(QCP::MarginSide side, QCPLayoutElement *element)
Definition: qcustomplot.cpp:3120
QCPAxisPainterPrivate::tickLabelsSelectionBox
QRect tickLabelsSelectionBox() const
Definition: qcustomplot.h:2401
QCPPolarAxisRadial::setTicker
void setTicker(QSharedPointer< QCPAxisTicker > ticker)
Definition: qcustomplot.cpp:31426
QCPAxisRect::~QCPAxisRect
virtual ~QCPAxisRect() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:17580
QCustomPlot::mBackgroundScaledMode
Qt::AspectRatioMode mBackgroundScaledMode
Definition: qcustomplot.h:3949
QCPAbstractPlottable1D< QCPGraphData >::dataCount
virtual int dataCount() const Q_DECL_OVERRIDE
Definition: qcustomplot.h:4382
QCPErrorBars::mSymbolGap
double mSymbolGap
Definition: qcustomplot.h:6358
QCPLabelPainterPrivate::asBottom
@ asBottom
Definition: qcustomplot.h:1584
QCP::sdPositive
@ sdPositive
The positive sign domain, i.e. numbers greater than zero.
Definition: qcustomplot.h:209
QCPAxisTickerText::setSubTickCount
void setSubTickCount(int subTicks)
Definition: qcustomplot.cpp:7266
QCPSelectionRect::canceled
void canceled(const QRect &rect, QInputEvent *event)
Definition: moc_qcustomplot.cpp:850
QCPTextElement::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19979
QCPAxisTickerFixed::ssNone
@ ssNone
Modifications are not allowed, the specified tick step is absolutely fixed. This might cause a high t...
Definition: qcustomplot.h:1873
QCPItemBracket::BracketStyle
BracketStyle
Definition: qcustomplot.h:6918
QCustomPlot::registerItem
bool registerItem(QCPAbstractItem *item)
Definition: qcustomplot.cpp:16252
QCustomPlot::itemDoubleClick
void itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3874
QCPLayoutGrid::FillOrder
FillOrder
Definition: qcustomplot.h:1368
QCPAbstractPlottable::selected
bool selected() const
Definition: qcustomplot.h:3486
QCPLabelPainterPrivate::padding
int padding() const
Definition: qcustomplot.h:1616
QCPPolarAxisRadial::mNumberFormatChar
QLatin1Char mNumberFormatChar
Definition: qcustomplot.h:7152
QCPAxis::selectionChanged
void selectionChanged(const QCPAxis::SelectableParts &parts)
Definition: moc_qcustomplot.cpp:2493
QCustomPlot::setMultiSelectModifier
void setMultiSelectModifier(Qt::KeyboardModifier modifier)
Definition: qcustomplot.cpp:13953
QCPLayerable::~QCPLayerable
virtual ~QCPLayerable()
Definition: qcustomplot.cpp:1383
QCPPainter::makeNonCosmetic
void makeNonCosmetic()
Definition: qcustomplot.cpp:479
QCPPolarGrid::setAntialiasedSubGrid
void setAntialiasedSubGrid(bool enabled)
Definition: qcustomplot.cpp:34188
QCustomPlot::xAxis2
QCPAxis * xAxis2
Definition: qcustomplot.h:3907
QCPPolarAxisRadial::SelectablePart
SelectablePart
Definition: qcustomplot.h:6996
QCPPolarAxisAngular::mNumberFormatChar
QLatin1Char mNumberFormatChar
Definition: qcustomplot.h:7425
QCPSelectionDecoratorBracket::mTangentToData
bool mTangentToData
Definition: qcustomplot.h:4871
QCPLabelPainterPrivate::drawLabelMaybeCached
virtual void drawLabelMaybeCached(QCPPainter *painter, const QFont &font, const QColor &color, const QPointF &pos, AnchorSide side, double rotation, const QString &text)
Definition: qcustomplot.cpp:5683
QCPMarginGroup::~QCPMarginGroup
virtual ~QCPMarginGroup()
Definition: qcustomplot.cpp:3051
QCPStatisticalBox::setWhiskerBarPen
void setWhiskerBarPen(const QPen &pen)
Definition: qcustomplot.cpp:25391
QCPLegend::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19565
QCPLabelPainterPrivate::LabelData::expBounds
QRect expBounds
Definition: qcustomplot.h:1645
QCPAxisPainterPrivate::getTickLabelData
virtual TickLabelData getTickLabelData(const QFont &font, const QString &text) const
Definition: qcustomplot.cpp:10341
QCPLineEnding::esNone
@ esNone
No ending decoration.
Definition: qcustomplot.h:1508
QCPAxis::setTickLabelFont
void setTickLabelFont(const QFont &font)
Definition: qcustomplot.cpp:8625
QCPPolarAxisRadial::mAADragBackup
QCP::AntialiasedElements mAADragBackup
Definition: qcustomplot.h:7175
QCPPainter::setModes
void setModes(PainterModes modes)
Definition: qcustomplot.cpp:405
QCPColorMap::updateMapImage
virtual void updateMapImage()
Definition: qcustomplot.cpp:26721
QCustomPlot::replot
Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpRefreshHint)
Definition: qcustomplot.cpp:15115
QCPItemStraightLine::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28877
QCPAxis::setSelectedBasePen
void setSelectedBasePen(const QPen &pen)
Definition: qcustomplot.cpp:9049
QCPBars::setData
void setData(QSharedPointer< QCPBarsDataContainer > data)
Definition: qcustomplot.cpp:24446
QCPAxis::selectedParts
SelectableParts selectedParts() const
Definition: qcustomplot.h:2211
QCPAxisTickerPi::simplifyFraction
void simplifyFraction(int &numerator, int &denominator) const
Definition: qcustomplot.cpp:7553
QCPCurve::getCurveLines
void getCurveLines(QVector< QPointF > *lines, const QCPDataRange &dataRange, double penWidth) const
Definition: qcustomplot.cpp:23033
QCPColorMap::mMapData
QCPColorMapData * mMapData
Definition: qcustomplot.h:6093
QCPPolarGrid::setAngularPen
void setAngularPen(const QPen &pen)
Definition: qcustomplot.cpp:34204
QCPItemPixmap::mScaledPixmap
QPixmap mScaledPixmap
Definition: qcustomplot.h:6793
QCPItemLine::pen
QPen pen() const
Definition: qcustomplot.h:6442
QCPSelectionDecoratorBracket::bsEllipse
@ bsEllipse
An ellipse is drawn. The size of the ellipse is given by the bracket width/height properties.
Definition: qcustomplot.h:4831
QCPAxis::mSelectedLabelFont
QFont mSelectedLabelFont
Definition: qcustomplot.h:2313
QCPAxisTickerDateTime::createTickVector
virtual QVector< double > createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:6735
QCPPolarAxisAngular::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:33066
QCPPolarAxisRadial::tickLengthOut
int tickLengthOut() const
Definition: qcustomplot.cpp:31162
QCPPlottableLegendItem::getFont
QFont getFont() const
Definition: qcustomplot.cpp:18939
QCPSelectionDecorator::usedScatterProperties
QCPScatterStyle::ScatterProperties usedScatterProperties() const
Definition: qcustomplot.h:3422
QCPItemPixmap::~QCPItemPixmap
virtual ~QCPItemPixmap() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30143
QCPItemPosition::ptAxisRectRatio
@ ptAxisRectRatio
Definition: qcustomplot.h:3620
QCPStatisticalBox::selectTestRect
virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:25479
QCPBars::mBarBelow
QPointer< QCPBars > mBarBelow
Definition: qcustomplot.h:5843
QCustomPlot::item
QCPAbstractItem * item() const
Definition: qcustomplot.cpp:14542
QCPVector2D::length
double length() const
Definition: qcustomplot.h:424
QCustomPlot::rpImmediateRefresh
@ rpImmediateRefresh
Replots immediately and repaints the widget immediately by calling QWidget::repaint() after the replo...
Definition: qcustomplot.h:3784
QCPItemText::mPadding
QMargins mPadding
Definition: qcustomplot.h:6665
QCPTextElement::mSelectable
bool mSelectable
Definition: qcustomplot.h:5291
QCPStatisticalBox::mWhiskerWidth
double mWhiskerWidth
Definition: qcustomplot.h:5956
QCPStatisticalBox::drawStatisticalBox
virtual void drawStatisticalBox(QCPPainter *painter, QCPStatisticalBoxDataContainer::const_iterator it, const QCPScatterStyle &outlierStyle) const
Definition: qcustomplot.cpp:25656
QCPScatterStyle::mSize
double mSize
Definition: qcustomplot.h:2548
QCPGraph::getFillBasePoint
QPointF getFillBasePoint(QPointF matchingDataPoint) const
Definition: qcustomplot.cpp:22118
QCPCurve::mScatterSkip
int mScatterSkip
Definition: qcustomplot.h:5647
QCustomPlot::processRectZoom
virtual Q_SLOT void processRectZoom(QRect rect, QMouseEvent *event)
Definition: qcustomplot.cpp:16118
QCPLayerable::visible
bool visible() const
Definition: qcustomplot.h:731
QCPPolarGraph::mDataContainer
QSharedPointer< QCPGraphDataContainer > mDataContainer
Definition: qcustomplot.h:7682
QCPLegend::getBorderPen
QPen getBorderPen() const
Definition: qcustomplot.cpp:19521
QCPFinancial::candlestickSelectTest
double candlestickSelectTest(const QPointF &pos, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, QCPFinancialDataContainer::const_iterator &closestDataPoint) const
Definition: qcustomplot.cpp:27735
QCPErrorBars::findBegin
virtual int findBegin(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28263
QCPAxisRect::mDragStartVertRange
QList< QCPRange > mDragStartVertRange
Definition: qcustomplot.h:4980
QCPItemBracket::bsCalligraphic
@ bsCalligraphic
A curly brace with varying stroke width giving a calligraphic impression.
Definition: qcustomplot.h:6921
QCPAxisRect::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18616
QCPTextElement::setSelectable
Q_SLOT void setSelectable(bool selectable)
Definition: qcustomplot.cpp:19854
QCPDataRange::isEmpty
bool isEmpty() const
Definition: qcustomplot.h:935
QCPSelectionDecoratorBracket::getTangentAngle
double getTangentAngle(const QCPPlottableInterface1D *interface1d, int dataIndex, int direction) const
Definition: qcustomplot.cpp:17342
QCPScatterStyle::ssPlus
@ ssPlus
\enumimage{ssPlus.png} a plus
Definition: qcustomplot.h:2495
QCPPolarGraph::addToLegend
bool addToLegend(QCPLegend *legend)
Definition: qcustomplot.cpp:34828
QCPLegend::font
QFont font() const
Definition: qcustomplot.h:5140
QCPAxisRect::mBackgroundPixmap
QPixmap mBackgroundPixmap
Definition: qcustomplot.h:4969
QCustomPlot::setAntialiasedElement
void setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled=true)
Definition: qcustomplot.cpp:13741
QCPDataRange::setBegin
void setBegin(int begin)
Definition: qcustomplot.h:930
QCustomPlot::hasPlottable
bool hasPlottable(QCPAbstractPlottable *plottable) const
Definition: qcustomplot.cpp:14370
QCPItemText::mSelectedFont
QFont mSelectedFont
Definition: qcustomplot.h:6660
QCPAbstractItem::selectableChanged
void selectableChanged(bool selectable)
Definition: moc_qcustomplot.cpp:3275
QCustomPlot::mouseDoubleClick
void mouseDoubleClick(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3818
QCPLineEnding::mLength
double mLength
Definition: qcustomplot.h:1545
QCPItemEllipse::aiLeft
@ aiLeft
Definition: qcustomplot.h:6726
QCPColorScale::rescaleDataRange
void rescaleDataRange(bool onlyVisibleMaps)
Definition: qcustomplot.cpp:20387
QCPPolarGraph::getOptimizedLineData
void getOptimizedLineData(QVector< QCPGraphData > *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const
Definition: qcustomplot.cpp:35364
QCPLegend::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:19118
QCP::stWhole
@ stWhole
Selection behaves like stMultipleDataRanges, but if there are any data points selected,...
Definition: qcustomplot.h:315
QCPAxisTickerPi::QCPAxisTickerPi
QCPAxisTickerPi()
Definition: qcustomplot.cpp:7427
QCPBars::wtAbsolute
@ wtAbsolute
Bar width is in absolute pixels.
Definition: qcustomplot.h:5795
QCPCurve::QCPCurve
QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:22618
QCPItemPosition::pixelPosition
virtual QPointF pixelPosition() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:12536
QCPTextElement::QCPTextElement
QCPTextElement(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:19660
QCPStatisticalBox::setWhiskerWidth
void setWhiskerWidth(double width)
Definition: qcustomplot.cpp:25361
QCPLayoutElement::setMaximumSize
void setMaximumSize(const QSize &size)
Definition: qcustomplot.cpp:3342
QCPAxisPainterPrivate::CachedLabel::offset
QPointF offset
Definition: qcustomplot.h:2433
QCPItemEllipse::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29996
QCPAbstractPlottable::setSelectionDecorator
void setSelectionDecorator(QCPSelectionDecorator *decorator)
Definition: qcustomplot.cpp:11573
QCPGraph::dataToLines
QVector< QPointF > dataToLines(const QVector< QCPGraphData > &data) const
Definition: qcustomplot.cpp:21325
QCPAxisRect::mBackgroundScaled
bool mBackgroundScaled
Definition: qcustomplot.h:4971
QCPSelectionDecoratorBracket::BracketStyle
BracketStyle
Definition: qcustomplot.h:4829
QCPAbstractPaintBuffer::setInvalidated
void setInvalidated(bool invalidated=true)
Definition: qcustomplot.cpp:624
QCPLayer::mode
LayerMode mode() const
Definition: qcustomplot.h:681
QCPItemLine::end
QCPItemPosition *const end
Definition: qcustomplot.h:6457
QCPTextElement::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19967
QCPAbstractPlottable::mPen
QPen mPen
Definition: qcustomplot.h:3530
QCPColorMapData::fillAlpha
void fillAlpha(unsigned char alpha)
Definition: qcustomplot.cpp:26186
QCPPolarAxisAngular::mScaledBackgroundPixmap
QPixmap mScaledBackgroundPixmap
Definition: qcustomplot.h:7401
QCPAxisTickerPi::mPeriodicity
int mPeriodicity
Definition: qcustomplot.h:1976
QCP::aeSubGrid
@ aeSubGrid
0x0004 Sub grid lines
Definition: qcustomplot.h:237
QCPColorGradient::gpGrayscale
@ gpGrayscale
Continuous lightness from black to white (suited for non-biased data representation)
Definition: qcustomplot.h:4746
QCPItemText::aiTop
@ aiTop
Definition: qcustomplot.h:6654
QCPScatterStyle::isNone
bool isNone() const
Definition: qcustomplot.h:2539
QCP::AntialiasedElement
AntialiasedElement
Definition: qcustomplot.h:235
QCustomPlot::toPainter
void toPainter(QCPPainter *painter, int width=0, int height=0)
Definition: qcustomplot.cpp:16453
QCPAxis::labelPadding
int labelPadding() const
Definition: qcustomplot.cpp:8328
QCPTextElement::mTextFlags
int mTextFlags
Definition: qcustomplot.h:5285
QCPLegend
Manages a legend inside a QCustomPlot.
Definition: qcustomplot.h:5101
QCPTextElement::mSelectedFont
QFont mSelectedFont
Definition: qcustomplot.h:5288
QCPLegend::spNone
@ spNone
0x000 None
Definition: qcustomplot.h:5126
QCPScatterStyle::ssNone
@ ssNone
no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines)
Definition: qcustomplot.h:2492
QCP
Definition: qcustomplot.h:160
QCPPolarAxisRadial::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32285
QCPPolarAxisRadial::setRangeZoomFactor
void setRangeZoomFactor(double factor)
Definition: qcustomplot.cpp:31195
QCustomPlot::selectedPlottables
QList< QCPAbstractPlottable * > selectedPlottables() const
Definition: qcustomplot.cpp:14342
QCPBarsGroup::stAxisRectRatio
@ stAxisRectRatio
Bar spacing is given by a fraction of the axis rect size.
Definition: qcustomplot.h:5695
QCPLayoutGrid::setFillOrder
void setFillOrder(FillOrder order, bool rearrange=true)
Definition: qcustomplot.cpp:4402
QCPItemRect::aiRight
@ aiRight
Definition: qcustomplot.h:6567
QCPDataRange::length
int length() const
Definition: qcustomplot.h:927
QCPItemRect::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29488
QCPPainter::restore
void restore()
Definition: qcustomplot.cpp:466
QCPPolarAxisRadial::getTickLabelFont
QFont getTickLabelFont() const
Definition: qcustomplot.cpp:32392
QCPFinancial::WidthType
WidthType
Definition: qcustomplot.h:6172
QCPDataContainer::const_iterator
QVector< DataType >::const_iterator const_iterator
Definition: qcustomplot.h:2581
QCPCurve::getScatters
void getScatters(QVector< QPointF > *scatters, const QCPDataRange &dataRange, double scatterWidth) const
Definition: qcustomplot.cpp:23136
QCPPolarGraph::mAntialiasedScatters
bool mAntialiasedScatters
Definition: qcustomplot.h:7686
QCPItemEllipse::brush
QBrush brush() const
Definition: qcustomplot.h:6701
QCPColorScale::mAxisRect
QPointer< QCPColorScaleAxisRectPrivate > mAxisRect
Definition: qcustomplot.h:5402
QCPPolarAxisAngular::center
QPointF center() const
Definition: qcustomplot.h:7388
QCPBarsGroup::bars
QList< QCPBars * > bars() const
Definition: qcustomplot.h:5712
QCPColorGradient::setNanHandling
void setNanHandling(NanHandling handling)
Definition: qcustomplot.cpp:16636
QCPPolarAxisAngular::addRadialAxis
QCPPolarAxisRadial * addRadialAxis(QCPPolarAxisRadial *axis=0)
Definition: qcustomplot.cpp:32720
QCPGraph::setScatterSkip
void setScatterSkip(int skip)
Definition: qcustomplot.cpp:20952
QCPPolarAxisAngular::mSubTicks
bool mSubTicks
Definition: qcustomplot.h:7430
QCPAxisTickerLog::mLogBaseLnInv
double mLogBaseLnInv
Definition: qcustomplot.h:2021
QCPLineEnding::mInverted
bool mInverted
Definition: qcustomplot.h:1546
QCustomPlot::mouseDoubleClickEvent
virtual void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15505
QCPPolarAxisRadial::rangeZoom
bool rangeZoom() const
Definition: qcustomplot.h:7015
QCPColorMapData::setRange
void setRange(const QCPRange &keyRange, const QCPRange &valueRange)
Definition: qcustomplot.cpp:25994
QCPErrorBars::dataSortKey
virtual double dataSortKey(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28168
QCPItemText::position
QCPItemPosition *const position
Definition: qcustomplot.h:6643
QCPAxisRect::graphs
QList< QCPGraph * > graphs() const
Definition: qcustomplot.cpp:17914
QCPBars::setWidthType
void setWidthType(WidthType widthType)
Definition: qcustomplot.cpp:24487
QCPLegend::setSelectedTextColor
void setSelectedTextColor(const QColor &color)
Definition: qcustomplot.cpp:19320
QCustomPlot::mousePress
void mousePress(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3825
QCPGraph::findIndexBelowY
int findIndexBelowY(const QVector< QPointF > *data, double y) const
Definition: qcustomplot.cpp:22443
QCPLabelPainterPrivate::setPadding
void setPadding(int padding)
Definition: qcustomplot.cpp:5538
QCPAbstractItem::mClipToAxisRect
bool mClipToAxisRect
Definition: qcustomplot.h:3717
QCPAxis::~QCPAxis
virtual ~QCPAxis() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:8265
QCPItemText::setPositionAlignment
void setPositionAlignment(Qt::Alignment alignment)
Definition: qcustomplot.cpp:29717
QCPCurve::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:22939
QCPLabelPainterPrivate::mAnchorReference
QPointF mAnchorReference
Definition: qcustomplot.h:1655
QCPItemBracket::style
BracketStyle style() const
Definition: qcustomplot.h:6932
QCPItemStraightLine::point1
QCPItemPosition *const point1
Definition: qcustomplot.h:6407
QCustomPlot::processPointSelection
virtual Q_SLOT void processPointSelection(QMouseEvent *event)
Definition: qcustomplot.cpp:16147
QCPItemBracket::aiCenter
@ aiCenter
Definition: qcustomplot.h:6949
QCPGraph::setData
void setData(QSharedPointer< QCPGraphDataContainer > data)
Definition: qcustomplot.cpp:20897
QCPLayoutGrid::~QCPLayoutGrid
virtual ~QCPLayoutGrid() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4112
QCPPolarAxisRadial::getTickLabelColor
QColor getTickLabelColor() const
Definition: qcustomplot.cpp:32412
QCPColorScale::setGradient
Q_SLOT void setGradient(const QCPColorGradient &gradient)
Definition: qcustomplot.cpp:20277
QCPFinancial::data
QSharedPointer< QCPFinancialDataContainer > data() const
Definition: qcustomplot.h:6192
QCPLayoutGrid::mFillOrder
FillOrder mFillOrder
Definition: qcustomplot.h:1425
QCustomPlot::setBufferDevicePixelRatio
void setBufferDevicePixelRatio(double ratio)
Definition: qcustomplot.cpp:14135
QCPLayerable::setAntialiased
void setAntialiased(bool enabled)
Definition: qcustomplot.cpp:1444
QCPAxisTicker::~QCPAxisTicker
virtual ~QCPAxisTicker()
Definition: qcustomplot.cpp:6126
QCPItemText::aiTopRight
@ aiTopRight
Definition: qcustomplot.h:6654
QCPLegend::itemCount
int itemCount() const
Definition: qcustomplot.cpp:19372
QCPColorScale::setDataScaleType
Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType)
Definition: qcustomplot.cpp:20257
QCPAxisTickerPi::mFractionStyle
FractionStyle mFractionStyle
Definition: qcustomplot.h:1977
QCPAbstractItem::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:13230
QCPLayerable::selectionCategory
virtual QCP::Interaction selectionCategory() const
Definition: qcustomplot.cpp:1640
QCPPolarAxisRadial::setRangeZoom
void setRangeZoom(bool enabled)
Definition: qcustomplot.cpp:31190
QCPAxis::mCachedMargin
int mCachedMargin
Definition: qcustomplot.h:2344
QCPPolarAxisRadial::mSelectedLabelColor
QColor mSelectedLabelColor
Definition: qcustomplot.h:7144
QCPLabelPainterPrivate::AnchorReferenceType
AnchorReferenceType
Definition: qcustomplot.h:1573
QCPSelectionDecoratorBracket::mTangentAverage
int mTangentAverage
Definition: qcustomplot.h:4872
QCPColorMapData::cell
double cell(int keyIndex, int valueIndex)
Definition: qcustomplot.cpp:25887
QCPItemCurve::mTail
QCPLineEnding mTail
Definition: qcustomplot.h:6514
QCPTextElement::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19914
QCustomPlot::setCurrentLayer
bool setCurrentLayer(const QString &name)
Definition: qcustomplot.cpp:14706
QCustomPlot::layoutElementAt
QCPLayoutElement * layoutElementAt(const QPointF &pos) const
Definition: qcustomplot.cpp:14961
QCustomPlot::minimumSizeHint
virtual QSize minimumSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15446
QCPAxisTickerDateTime::dsUniformTimeInDay
@ dsUniformTimeInDay
Definition: qcustomplot.h:1796
QCPColorScale::dataRange
QCPRange dataRange() const
Definition: qcustomplot.h:5363
QCPLegend::parentPlotInitialized
virtual void parentPlotInitialized(QCustomPlot *parentPlot) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19604
QCPCurveData
Holds the data of one single data point for QCPCurve.
Definition: qcustomplot.h:5565
QCPLayerable::layer
QCPLayer * layer() const
Definition: qcustomplot.h:734
QCPAxisRect::mRangeDragHorzAxis
QList< QPointer< QCPAxis > > mRangeDragHorzAxis
Definition: qcustomplot.h:4975
QCPPolarAxisAngular::setAngle
void setAngle(double degrees)
Definition: qcustomplot.cpp:33325
QCPPolarAxisAngular::setSubTicks
void setSubTicks(bool show)
Definition: qcustomplot.cpp:33581
QCPLayerable::mAntialiased
bool mAntialiased
Definition: qcustomplot.h:758
QCPAbstractPlottable::brush
QBrush brush() const
Definition: qcustomplot.h:3482
QCPItemTracer::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:30433
QCPGrid::setSubGridPen
void setSubGridPen(const QPen &pen)
Definition: qcustomplot.cpp:7910
QCPPolarAxisRadial::setTickLabels
void setTickLabels(bool show)
Definition: qcustomplot.cpp:31455
QCustomPlot::axisRectCount
int axisRectCount() const
Definition: qcustomplot.cpp:14881
QCPLayer
A layer that may contain objects, to control the rendering order.
Definition: qcustomplot.h:647
QCPPolarAxisRadial::scaleTypeChanged
void scaleTypeChanged(QCPPolarAxisRadial::ScaleType scaleType)
Definition: moc_qcustomplot.cpp:8293
QCPCurve::mScatterStyle
QCPScatterStyle mScatterStyle
Definition: qcustomplot.h:5646
QCPPolarAxisRadial::setSelectedSubTickPen
void setSelectedSubTickPen(const QPen &pen)
Definition: qcustomplot.cpp:31874
QCPFinancial::mWidth
double mWidth
Definition: qcustomplot.h:6230
QCPAxis::mTickVector
QVector< double > mTickVector
Definition: qcustomplot.h:2340
QCPMarginGroup::QCPMarginGroup
QCPMarginGroup(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:3041
QCPLineEnding::esSkewedBar
@ esSkewedBar
A bar that is skewed (skew controllable via setLength)
Definition: qcustomplot.h:1517
QCPItemText::mPositionAlignment
Qt::Alignment mPositionAlignment
Definition: qcustomplot.h:6662
QCPPolarAxisRadial::setTickLabelMode
void setTickLabelMode(LabelMode mode)
Definition: qcustomplot.cpp:31513
QCPAxisPainterPrivate::TickLabelData::expBounds
QRect expBounds
Definition: qcustomplot.h:2439
QCPDataSelection::operator+=
QCPDataSelection & operator+=(const QCPDataSelection &other)
Definition: qcustomplot.cpp:2450
QCPPolarAxisAngular::mGraphs
QList< QCPPolarGraph * > mGraphs
Definition: qcustomplot.h:7443
QCPTextElement::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19928
QCPPolarAxisAngular::setBackgroundScaled
void setBackgroundScaled(bool scaled)
Definition: qcustomplot.cpp:33136
QCPPolarAxisRadial::mAngle
double mAngle
Definition: qcustomplot.h:7136
QCPCurve::drawCurveLine
virtual void drawCurveLine(QCPPainter *painter, const QVector< QPointF > &lines) const
Definition: qcustomplot.cpp:22979
QCPItemText::setText
void setText(const QString &text)
Definition: qcustomplot.cpp:29700
QCPAxis::setTickLength
void setTickLength(int inside, int outside=0)
Definition: qcustomplot.cpp:8787
QCPFinancial::setTwoColored
void setTwoColored(bool twoColored)
Definition: qcustomplot.cpp:27160
QCPPolarGraph::applyScattersAntialiasingHint
void applyScattersAntialiasingHint(QCPPainter *painter) const
Definition: qcustomplot.cpp:35149
QCPScatterStyle::ssCrossCircle
@ ssCrossCircle
\enumimage{ssCrossCircle.png} a circle with a cross inside
Definition: qcustomplot.h:2505
QCPPaintBufferPixmap::mBuffer
QPixmap mBuffer
Definition: qcustomplot.h:587
QCPFinancialDataContainer
QCPDataContainer< QCPFinancialData > QCPFinancialDataContainer
Definition: qcustomplot.h:6150
QCPLabelPainterPrivate::asBottomRight
@ asBottomRight
Definition: qcustomplot.h:1587
QCPColorGradient::mColorInterpolation
ColorInterpolation mColorInterpolation
Definition: qcustomplot.h:4795
QCPSelectionDecoratorBracket::bsHalfEllipse
@ bsHalfEllipse
A half ellipse is drawn. The size of the ellipse is given by the bracket width/height properties.
Definition: qcustomplot.h:4830
QCPLabelPainterPrivate::setAbbreviateDecimalPowers
void setAbbreviateDecimalPowers(bool enabled)
Definition: qcustomplot.cpp:5558
QCPAxisTickerText::createTickVector
virtual QVector< double > createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7381
QCPCurve::getTraverseCornerPoints
void getTraverseCornerPoints(int prevRegion, int currentRegion, double keyMin, double valueMax, double keyMax, double valueMin, QVector< QPointF > &beforeTraverse, QVector< QPointF > &afterTraverse) const
Definition: qcustomplot.cpp:23774
QCPLabelPainterPrivate::AnchorMode
AnchorMode
Definition: qcustomplot.h:1564
QCPColorScale::update
virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20447
QCPLegend::setSelectedParts
Q_SLOT void setSelectedParts(const SelectableParts &selectedParts)
Definition: qcustomplot.cpp:19239
QCPItemBracket::QCPItemBracket
QCPItemBracket(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:30767
QCPErrorBars::rectIntersectsLine
bool rectIntersectsLine(const QRectF &pixelRect, const QLineF &line) const
Definition: qcustomplot.cpp:28803
QCPPolarAxisRadial::setSelectedTickLabelColor
void setSelectedTickLabelColor(const QColor &color)
Definition: qcustomplot.cpp:31831
QCPSelectionRect::mRect
QRect mRect
Definition: qcustomplot.h:1147
QCPColorScale::setRangeZoom
void setRangeZoom(bool enabled)
Definition: qcustomplot.cpp:20345
QCPLayerable::clipRect
virtual QRect clipRect() const
Definition: qcustomplot.cpp:1654
QCPColorMapData::valueSize
int valueSize() const
Definition: qcustomplot.h:5995
QCPAbstractPlottable::name
QString name() const
Definition: qcustomplot.h:3478
QCPAxisTickerTime::setFieldWidth
void setFieldWidth(TimeUnit unit, int width)
Definition: qcustomplot.cpp:6947
QCPPolarGraph::coordsToPixels
void coordsToPixels(double key, double value, double &x, double &y) const
Definition: qcustomplot.cpp:34721
QCPAxis::mScaleType
ScaleType mScaleType
Definition: qcustomplot.h:2334
QCPPolarAxisAngular::pixelToCoord
void pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const
Definition: qcustomplot.cpp:32864
QCPItemCurve::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29328
QCPPolarGraph::mPeriodic
bool mPeriodic
Definition: qcustomplot.h:7689
QCPAxisTickerTime::tuSeconds
@ tuSeconds
Seconds (%s in setTimeFormat)
Definition: qcustomplot.h:1821
QCPAbstractItem::setSelectable
Q_SLOT void setSelectable(bool selectable)
Definition: qcustomplot.cpp:12990
QCPCurve::mLineStyle
LineStyle mLineStyle
Definition: qcustomplot.h:5648
QCPColorMap::setInterpolate
void setInterpolate(bool enabled)
Definition: qcustomplot.cpp:26515
QCPPolarGraph::keyAxis
QCPPolarAxisAngular * keyAxis() const
Definition: qcustomplot.h:7627
QCPLineEnding
Handles the different ending decorations for line-like items.
Definition: qcustomplot.h:1493
QCPPolarGraph::mBrush
QBrush mBrush
Definition: qcustomplot.h:7688
QCPColorScaleAxisRectPrivate::updateGradientImage
void updateGradientImage()
Definition: qcustomplot.cpp:20612
QCPAbstractLegendItem::mParentLegend
QCPLegend * mParentLegend
Definition: qcustomplot.h:5054
QCPLayerable::realVisibility
bool realVisibility() const
Definition: qcustomplot.cpp:1459
QCPLayoutElement::setSizeConstraintRect
void setSizeConstraintRect(SizeConstraintRect constraintRect)
Definition: qcustomplot.cpp:3373
QCPAxis::setRangeUpper
void setRangeUpper(double upper)
Definition: qcustomplot.cpp:8522
QCPAxisRect::setBackgroundScaledMode
void setBackgroundScaledMode(Qt::AspectRatioMode mode)
Definition: qcustomplot.cpp:18095
QCPSelectionDecorator::~QCPSelectionDecorator
virtual ~QCPSelectionDecorator()
Definition: qcustomplot.cpp:11064
QCPPaintBufferPixmap
A paint buffer based on QPixmap, using software raster rendering.
Definition: qcustomplot.h:574
QCPItemEllipse::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:30077
QCPFinancialData::low
double low
Definition: qcustomplot.h:6136
QCPLegend::setSelectedFont
void setSelectedFont(const QFont &font)
Definition: qcustomplot.cpp:19303
QCPSelectionDecoratorBracket::getPixelCoordinates
QPointF getPixelCoordinates(const QCPPlottableInterface1D *interface1d, int dataIndex) const
Definition: qcustomplot.cpp:17389
QCPItemPixmap::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30201
QCPColorGradient::setLevelCount
void setLevelCount(int n)
Definition: qcustomplot.cpp:16572
QCPColorGradient::gpPolar
@ gpPolar
Colors suitable to emphasize polarity around the center, with blue for negative, black in the middle ...
Definition: qcustomplot.h:4754
QCPAbstractPlottable::selection
QCPDataSelection selection() const
Definition: qcustomplot.h:3487
QCPFinancial::timeSeriesToOhlc
static QCPFinancialDataContainer timeSeriesToOhlc(const QVector< double > &time, const QVector< double > &value, double timeBinSize, double timeBinOffset=0)
Definition: qcustomplot.cpp:27372
QCPAbstractPlottable::setAntialiasedFill
void setAntialiasedFill(bool enabled)
Definition: qcustomplot.cpp:11459
QCPFinancial::mTwoColored
bool mTwoColored
Definition: qcustomplot.h:6232
QCPItemText::mText
QString mText
Definition: qcustomplot.h:6661
QCPAxisPainterPrivate::size
virtual int size()
Definition: qcustomplot.cpp:10123
QCustomPlot::setBackgroundScaledMode
void setBackgroundScaledMode(Qt::AspectRatioMode mode)
Definition: qcustomplot.cpp:14226
QCustomPlot::mMouseHasMoved
bool mMouseHasMoved
Definition: qcustomplot.h:3960
QCPTextElement::selectable
bool selectable() const
Definition: qcustomplot.h:5257
QCustomPlot::mMouseSignalLayerable
QPointer< QCPLayerable > mMouseSignalLayerable
Definition: qcustomplot.h:3962
QCPAbstractPaintBuffer::reallocateBuffer
virtual void reallocateBuffer()=0
QCPSelectionRect::changed
void changed(const QRect &rect, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:843
QCPGrid::drawSubGridLines
void drawSubGridLines(QCPPainter *painter) const
Definition: qcustomplot.cpp:8037
QCPPolarAxisAngular::radialAxisCount
int radialAxisCount() const
Definition: qcustomplot.cpp:32664
QCPPolarGraph::lsNone
@ lsNone
Definition: qcustomplot.h:7611
QCPBars::width
double width() const
Definition: qcustomplot.h:5805
QCPLegend::selectionChanged
void selectionChanged(QCPLegend::SelectableParts parts)
Definition: moc_qcustomplot.cpp:4783
QCPAxisPainterPrivate::substituteExponent
bool substituteExponent
Definition: qcustomplot.h:2415
QCPAxis::setSelectedLabelFont
void setSelectedLabelFont(const QFont &font)
Definition: qcustomplot.cpp:9015
QCPPolarAxisAngular::drawBackground
void drawBackground(QCPPainter *painter, const QPointF &center, double radius)
Definition: qcustomplot.cpp:33811
QCustomPlot::selectedItems
QList< QCPAbstractItem * > selectedItems() const
Definition: qcustomplot.cpp:14617
QCPAxis::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9520
QCPSelectionDecorator::copyFrom
virtual void copyFrom(const QCPSelectionDecorator *other)
Definition: qcustomplot.cpp:11155
QCPBars::mBarAbove
QPointer< QCPBars > mBarAbove
Definition: qcustomplot.h:5843
QCPBarsGroup::QCPBarsGroup
QCPBarsGroup(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:23993
QCPItemText::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:29647
QCPBars::setBarsGroup
void setBarsGroup(QCPBarsGroup *barsGroup)
Definition: qcustomplot.cpp:24498
QCPLineEnding::QCPLineEnding
QCPLineEnding()
Definition: qcustomplot.cpp:5193
QCPPolarAxisAngular::selectionChanged
void selectionChanged(const QCPPolarAxisAngular::SelectableParts &parts)
Definition: moc_qcustomplot.cpp:8520
QCPAxisPainterPrivate::TickLabelData
Definition: qcustomplot.h:2436
QCPLabelPainterPrivate::asRight
@ asRight
Definition: qcustomplot.h:1582
QCPPainter::pmNoCaching
@ pmNoCaching
0x02 Mode for all sorts of exports (e.g. PNG, PDF,...). For example, this prevents using cached pixma...
Definition: qcustomplot.h:490
QCPGraph::getChannelFillPolygon
const QPolygonF getChannelFillPolygon(const QVector< QPointF > *thisData, QCPDataRange thisSegment, const QVector< QPointF > *otherData, QCPDataRange otherSegment) const
Definition: qcustomplot.cpp:22208
QCPBars::QCPBars
QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:24408
QCPColorGradient::GradientPreset
GradientPreset
Definition: qcustomplot.h:4746
QCustomPlot::hasItem
bool hasItem(QCPAbstractItem *item) const
Definition: qcustomplot.cpp:14647
QCustomPlot::layerableListAt
QList< QCPLayerable * > layerableListAt(const QPointF &pos, bool onlySelectable, QList< QVariant > *selectionDetails=nullptr) const
Definition: qcustomplot.cpp:16329
QCPTextElement::doubleClicked
void doubleClicked(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:5045
QCPPainter::setAntialiasing
void setAntialiasing(bool enabled)
Definition: qcustomplot.cpp:385
QCPItemAnchor::name
QString name() const
Definition: qcustomplot.h:3576
QCPLegend::setSelectedIconBorderPen
void setSelectedIconBorderPen(const QPen &pen)
Definition: qcustomplot.cpp:19280
QCPPolarAxisRadial::mSelectedTickLabelColor
QColor mSelectedTickLabelColor
Definition: qcustomplot.h:7150
QCustomPlot::savePng
bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
Definition: qcustomplot.cpp:15342
QCPLayerable::mLayer
QCPLayer * mLayer
Definition: qcustomplot.h:757
QCPStatisticalBox::data
QSharedPointer< QCPStatisticalBoxDataContainer > data() const
Definition: qcustomplot.h:5923
QCPColorMapData::fill
void fill(double z)
Definition: qcustomplot.cpp:26168
QCPLayer::mVisible
bool mVisible
Definition: qcustomplot.h:696
QCustomPlot::graphCount
int graphCount() const
Definition: qcustomplot.cpp:14491
QCPAxis::mNotAADragBackup
QCP::AntialiasedElements mNotAADragBackup
Definition: qcustomplot.h:2347
QCPAxisPainterPrivate::placeTickLabel
virtual void placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize)
Definition: qcustomplot.cpp:10213
QCPPolarAxisAngular::coordToAngleRad
double coordToAngleRad(double coord) const
Definition: qcustomplot.h:7370
QCPItemPosition::value
double value() const
Definition: qcustomplot.h:3638
QCPPolarAxisRadial::selectableChanged
void selectableChanged(const QCPPolarAxisRadial::SelectableParts &parts)
Definition: moc_qcustomplot.cpp:8307
QCPBarsGroup::registerBars
void registerBars(QCPBars *bars)
Definition: qcustomplot.cpp:24129
QCPAxisRect::setRangeDragAxes
void setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical)
Definition: qcustomplot.cpp:18242
QCPDataSelection::intersection
QCPDataSelection intersection(const QCPDataRange &other) const
Definition: qcustomplot.cpp:2708
QCPPolarAxisAngular::setLabelPadding
void setLabelPadding(int padding)
Definition: qcustomplot.cpp:33706
QCustomPlot::selectionChangedByUser
void selectionChangedByUser()
Definition: moc_qcustomplot.cpp:3909
QCPColorScale::dataScaleTypeChanged
void dataScaleTypeChanged(QCPAxis::ScaleType scaleType)
Definition: moc_qcustomplot.cpp:5427
QCPAbstractPlottable::keyAxis
QCPAxis * keyAxis() const
Definition: qcustomplot.h:3483
QCPAxisTickerFixed::mTickStep
double mTickStep
Definition: qcustomplot.h:1891
QCPLabelPainterPrivate::mColor
QColor mColor
Definition: qcustomplot.h:1658
QCPAxis::mSubTicks
bool mSubTicks
Definition: qcustomplot.h:2327
QCPAxisPainterPrivate::TickLabelData::totalBounds
QRect totalBounds
Definition: qcustomplot.h:2439
QCPScatterStyle::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:10812
QCPColorGradient::mColorBufferInvalidated
bool mColorBufferInvalidated
Definition: qcustomplot.h:4802
QCPGraph::setScatterStyle
void setScatterStyle(const QCPScatterStyle &style)
Definition: qcustomplot.cpp:20936
QCPAxis::setSelectedParts
Q_SLOT void setSelectedParts(const QCPAxis::SelectableParts &selectedParts)
Definition: qcustomplot.cpp:8437
QCPPolarAxisAngular::mRange
QCPRange mRange
Definition: qcustomplot.h:7435
QCPFinancial::wtAbsolute
@ wtAbsolute
width is in absolute pixels
Definition: qcustomplot.h:6172
QCPAxisTickerPi::fsFloatingPoint
@ fsFloatingPoint
Fractions are displayed as regular decimal floating point numbers, e.g. "0.25" or "0....
Definition: qcustomplot.h:1952
QCustomPlot::axisRects
QList< QCPAxisRect * > axisRects() const
Definition: qcustomplot.cpp:14929
QCPPolarAxisAngular::mSelectedTickLabelFont
QFont mSelectedTickLabelFont
Definition: qcustomplot.h:7422
QCPStatisticalBox::mWhiskerPen
QPen mWhiskerPen
Definition: qcustomplot.h:5957
QCPLayerable::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
Definition: qcustomplot.cpp:1690
QCPColorMapData::data
double data(double key, double value)
Definition: qcustomplot.cpp:25876
QCPPolarAxisRadial::mRangeZoomFactor
double mRangeZoomFactor
Definition: qcustomplot.h:7132
QCPPolarAxisAngular::setRangeZoom
void setRangeZoom(bool enabled)
Definition: qcustomplot.cpp:33156
QCPVector2D::distanceToStraightLine
double distanceToStraightLine(const QCPVector2D &base, const QCPVector2D &direction) const
Definition: qcustomplot.cpp:225
QCPPolarGraph::selectionCategory
virtual QCP::Interaction selectionCategory() const
Definition: qcustomplot.cpp:35003
QCPBars::wtAxisRectRatio
@ wtAxisRectRatio
Bar width is given by a fraction of the axis rect size.
Definition: qcustomplot.h:5796
QCPFinancial::mBrushNegative
QBrush mBrushNegative
Definition: qcustomplot.h:6233
QCPStatisticalBox::mOutlierStyle
QCPScatterStyle mOutlierStyle
Definition: qcustomplot.h:5960
QCPLayerable::QCPLayerable
QCPLayerable(QCustomPlot *plot, QString targetLayer=QString(), QCPLayerable *parentLayerable=nullptr)
Definition: qcustomplot.cpp:1366
QCPStatisticalBox::getWhiskerBackboneLines
QVector< QLineF > getWhiskerBackboneLines(QCPStatisticalBoxDataContainer::const_iterator it) const
Definition: qcustomplot.cpp:25731
QCPPolarGraph::setName
void setName(const QString &name)
Definition: qcustomplot.cpp:34464
QCPTextElement::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19949
QCPAxisTickerText::ticks
QMap< double, QString > & ticks()
Definition: qcustomplot.h:1911
QCPItemRect::aiTopRight
@ aiTopRight
Definition: qcustomplot.h:6567
QCPGraph::data
QSharedPointer< QCPGraphDataContainer > data() const
Definition: qcustomplot.h:5487
QCPColorGradient::gpThermal
@ gpThermal
Colors suitable for thermal imaging, ranging from dark blue over purple to orange,...
Definition: qcustomplot.h:4753
QCustomPlot::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15557
QCPErrorBarsData::QCPErrorBarsData
QCPErrorBarsData()
Definition: qcustomplot.cpp:27876
QCPLayoutGrid::getMaximumRowColSizes
void getMaximumRowColSizes(QVector< int > *maxColWidths, QVector< int > *maxRowHeights) const
Definition: qcustomplot.cpp:4832
QCPAxisTickerText::addTick
void addTick(double position, const QString &label)
Definition: qcustomplot.cpp:7293
QCPStatisticalBox::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:25573
QCPLegend::selectableChanged
void selectableChanged(QCPLegend::SelectableParts parts)
Definition: moc_qcustomplot.cpp:4790
QCPLayoutInset::QCPLayoutInset
QCPLayoutInset()
Definition: qcustomplot.cpp:4887
QCPItemRect::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:29460
QCPItemEllipse::aiBottom
@ aiBottom
Definition: qcustomplot.h:6726
QCPItemText::aiRight
@ aiRight
Definition: qcustomplot.h:6654
QCPAxisRect::mRangeZoomHorzAxis
QList< QPointer< QCPAxis > > mRangeZoomHorzAxis
Definition: qcustomplot.h:4976
QCustomPlot::legendClick
void legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3895
QCPPolarAxisRadial::mRadius
double mRadius
Definition: qcustomplot.h:7168
QCPAxisRect::setRangeDrag
void setRangeDrag(Qt::Orientations orientations)
Definition: qcustomplot.cpp:18206
QCPItemText::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6658
QCPAxisRect::setBackgroundScaled
void setBackgroundScaled(bool scaled)
Definition: qcustomplot.cpp:18085
QCPLabelPainterPrivate::mPadding
int mPadding
Definition: qcustomplot.h:1659
QCPLayout::getFinalMinimumOuterSize
static QSize getFinalMinimumOuterSize(const QCPLayoutElement *el)
Definition: qcustomplot.cpp:4020
QCPItemPixmap::aiRight
@ aiRight
Definition: qcustomplot.h:6789
QCustomPlot::axisRemoved
virtual void axisRemoved(QCPAxis *axis)
Definition: qcustomplot.cpp:15988
QCPAxisTickerTime::mFormatPattern
QHash< TimeUnit, QString > mFormatPattern
Definition: qcustomplot.h:1845
QCPColorGradient::setColorInterpolation
void setColorInterpolation(ColorInterpolation interpolation)
Definition: qcustomplot.cpp:16622
QCPAbstractItem::mAnchors
QList< QCPItemAnchor * > mAnchors
Definition: qcustomplot.h:3720
QCPDataSelection::dataRangeCount
int dataRangeCount() const
Definition: qcustomplot.h:973
QCPVector2D
Represents two doubles as a mathematical 2D vector.
Definition: qcustomplot.h:405
QCPItemEllipse::bottomRight
QCPItemPosition *const bottomRight
Definition: qcustomplot.h:6714
QCPItemTracer::mInterpolating
bool mInterpolating
Definition: qcustomplot.h:6885
QCPAxis::mLabel
QString mLabel
Definition: qcustomplot.h:2312
QCPAxisPainterPrivate::TickLabelData::rotatedTotalBounds
QRect rotatedTotalBounds
Definition: qcustomplot.h:2439
QCPPlottableInterface1D::dataCount
virtual int dataCount() const =0
QCPColorScale::wheelEvent
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20522
QCPItemPosition::mParentAnchorX
QCPItemAnchor * mParentAnchorX
Definition: qcustomplot.h:3664
QCPBars::connectBars
static void connectBars(QCPBars *lower, QCPBars *upper)
Definition: qcustomplot.cpp:25063
QCPPolarAxisAngular::setBasePen
void setBasePen(const QPen &pen)
Definition: qcustomplot.cpp:33639
QCP::iSelectItems
@ iSelectItems
0x040 Items are selectable (Rectangles, Arrows, Textitems, etc. see QCPAbstractItem)
Definition: qcustomplot.h:279
QCPLabelPainterPrivate::drawText
void drawText(QCPPainter *painter, const QPointF &pos, const LabelData &labelData) const
Definition: qcustomplot.cpp:5784
QCPSelectionRect::started
void started(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:836
QCPAbstractPlottable::~QCPAbstractPlottable
virtual ~QCPAbstractPlottable() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:11435
QCPPolarGraph::mScatterStyle
QCPScatterStyle mScatterStyle
Definition: qcustomplot.h:7684
QCPPolarGrid::mAngularSubGridPen
QPen mAngularSubGridPen
Definition: qcustomplot.h:7544
QCPFinancial::setChartStyle
void setChartStyle(ChartStyle style)
Definition: qcustomplot.cpp:27123
QCPSelectionRect::mActive
bool mActive
Definition: qcustomplot.h:1151
QCPPolarAxisAngular::mTicker
QSharedPointer< QCPAxisTicker > mTicker
Definition: qcustomplot.h:7444
QCPScatterStyle::ssCross
@ ssCross
\enumimage{ssCross.png} a cross
Definition: qcustomplot.h:2494
QCPAbstractPaintBuffer::invalidated
bool invalidated() const
Definition: qcustomplot.h:547
QCustomPlot::afterLayout
void afterLayout()
Definition: moc_qcustomplot.cpp:3921
QCPAxisTickerText::clear
void clear()
Definition: qcustomplot.cpp:7282
QCPAxis::spAxis
@ spAxis
The axis backbone and tick marks.
Definition: qcustomplot.h:2168
QCPAxisTickerLog::setLogBase
void setLogBase(double base)
Definition: qcustomplot.cpp:7735
QCPAxis::atRight
@ atRight
0x02 Axis is vertical and on the right side of the axis rect
Definition: qcustomplot.h:2139
QCPPolarAxisAngular::QCPPolarAxisAngular
QCPPolarAxisAngular(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:32539
QCPSelectionRect::range
QCPRange range(const QCPAxis *axis) const
Definition: qcustomplot.cpp:2863
QCPScatterStyle::ssCircle
@ ssCircle
\enumimage{ssCircle.png} a circle
Definition: qcustomplot.h:2496
QCPAbstractItem::selected
bool selected() const
Definition: qcustomplot.h:3693
QCPAxis::setTickPen
void setTickPen(const QPen &pen)
Definition: qcustomplot.cpp:8898
QCustomPlot::itemCount
int itemCount() const
Definition: qcustomplot.cpp:14607
QCPAbstractPlottable::applyDefaultAntialiasingHint
void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:11909
QCPGraph::segmentsIntersect
bool segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, int &bPrecedence) const
Definition: qcustomplot.cpp:22085
QCPBarsGroup::insert
void insert(int i, QCPBars *bars)
Definition: qcustomplot.cpp:24088
QCPPolarGraph::dataToLines
QVector< QPointF > dataToLines(const QVector< QCPGraphData > &data) const
Definition: qcustomplot.cpp:35481
QCPColorGradient::mColorBuffer
QVector< QRgb > mColorBuffer
Definition: qcustomplot.h:4801
QCPScatterStyle::mPixmap
QPixmap mPixmap
Definition: qcustomplot.h:2552
QCPAxis::mTickPen
QPen mTickPen
Definition: qcustomplot.h:2329
QCPAxis::atTop
@ atTop
0x04 Axis is horizontal and on the top side of the axis rect
Definition: qcustomplot.h:2140
QCPPolarAxisRadial::mLabelPainter
QCPLabelPainterPrivate mLabelPainter
Definition: qcustomplot.h:7176
QCPPolarAxisRadial::mSubTickVector
QVector< double > mSubTickVector
Definition: qcustomplot.h:7172
QCP::aeFills
@ aeFills
0x0100 Borders of fills (e.g. under or between graphs)
Definition: qcustomplot.h:243
QCPLabelPainterPrivate::mFont
QFont mFont
Definition: qcustomplot.h:1657
QCPPolarAxisRadial::spAxis
@ spAxis
The axis backbone and tick marks.
Definition: qcustomplot.h:6997
QCPAxisTickerPi::unicodeSubscript
QString unicodeSubscript(int number) const
Definition: qcustomplot.cpp:7672
QCPAxis::mSelectedTickPen
QPen mSelectedTickPen
Definition: qcustomplot.h:2329
QCPPolarAxisRadial::subTickLengthIn
int subTickLengthIn() const
Definition: qcustomplot.cpp:31168
QCPColorMapData::dataBounds
QCPRange dataBounds() const
Definition: qcustomplot.h:5998
QCPItemText::pen
QPen pen() const
Definition: qcustomplot.h:6613
QCPPaintBufferPixmap::~QCPPaintBufferPixmap
virtual ~QCPPaintBufferPixmap() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:673
QCPAxis::setLabelColor
void setLabelColor(const QColor &color)
Definition: qcustomplot.cpp:8932
QCPItemAnchor::mChildrenX
QSet< QCPItemPosition * > mChildrenX
Definition: qcustomplot.h:3587
QCPAxis::setSubTickLengthOut
void setSubTickLengthOut(int outside)
Definition: qcustomplot.cpp:8874
QCPColorMapData::coordToCell
void coordToCell(double key, double value, int *keyIndex, int *valueIndex) const
Definition: qcustomplot.cpp:26214
QCPVector2D::operator*=
QCPVector2D & operator*=(double factor)
Definition: qcustomplot.cpp:234
QCustomPlot::antialiasedElements
QCP::AntialiasedElements antialiasedElements() const
Definition: qcustomplot.h:3801
QCPLayoutElement::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:3525
QCPAbstractPlottable::mAntialiasedScatters
bool mAntialiasedScatters
Definition: qcustomplot.h:3529
QCPErrorBars::mWhiskerWidth
double mWhiskerWidth
Definition: qcustomplot.h:6357
QCPItemBracket::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6950
QCustomPlot::layer
QCPLayer * layer(const QString &name) const
Definition: qcustomplot.cpp:14660
QCPGraph::lsStepRight
@ lsStepRight
line is drawn as steps where the step height is the value of the right data point
Definition: qcustomplot.h:5477
QCPGraph::drawLinePlot
virtual void drawLinePlot(QCPPainter *painter, const QVector< QPointF > &lines) const
Definition: qcustomplot.cpp:21618
QCPColorGradient::setColorStopAt
void setColorStopAt(double position, const QColor &color)
Definition: qcustomplot.cpp:16609
QCPPolarAxisRadial::mNotAADragBackup
QCP::AntialiasedElements mNotAADragBackup
Definition: qcustomplot.h:7175
QCPItemBracket::left
QCPItemPosition *const left
Definition: qcustomplot.h:6943
QCPPolarAxisAngular::wheelEvent
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:34063
QCPColorGradient::mNanColor
QColor mNanColor
Definition: qcustomplot.h:4797
QCPPolarGraph::QCPPolarGraph
QCPPolarGraph(QCPPolarAxisAngular *keyAxis, QCPPolarAxisRadial *valueAxis)
Definition: qcustomplot.cpp:34423
QCPLayerable::wheelEvent
virtual void wheelEvent(QWheelEvent *event)
Definition: qcustomplot.cpp:1831
QCPPolarAxisAngular::radialAxis
QCPPolarAxisRadial * radialAxis(int index=0) const
Definition: qcustomplot.cpp:32674
QCPPolarAxisAngular::mTickPen
QPen mTickPen
Definition: qcustomplot.h:7432
QCPColorMapData::setData
void setData(double key, double value, double z)
Definition: qcustomplot.cpp:26042
QCPLabelPainterPrivate::LabelData::expPart
QString expPart
Definition: qcustomplot.h:1644
QCPSelectionRect::pen
QPen pen() const
Definition: qcustomplot.h:1128
QCPGraph::findIndexBelowX
int findIndexBelowX(const QVector< QPointF > *data, double x) const
Definition: qcustomplot.cpp:22338
QCPLayer::index
int index() const
Definition: qcustomplot.h:678
QCPAxisTickerTime::getTickLabel
virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7038
QCustomPlot::xAxis
QCPAxis * xAxis
Definition: qcustomplot.h:3907
QCPAbstractItem::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:13244
QCPLayoutElement::margins
QMargins margins() const
Definition: qcustomplot.h:1247
QCPPainter::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:328
QCPAxisPainterPrivate::TickLabelData::baseBounds
QRect baseBounds
Definition: qcustomplot.h:2439
QCPPolarAxisAngular::mSubTickLengthIn
int mSubTickLengthIn
Definition: qcustomplot.h:7431
QCPFinancial::setWidthType
void setWidthType(WidthType widthType)
Definition: qcustomplot.cpp:27146
QCPAxisRect::setBackground
void setBackground(const QPixmap &pm)
Definition: qcustomplot.cpp:18036
QCPLabelPainterPrivate::asLeft
@ asLeft
Definition: qcustomplot.h:1581
QCPItemEllipse::pen
QPen pen() const
Definition: qcustomplot.h:6699
QCPGraph::mLineStyle
LineStyle mLineStyle
Definition: qcustomplot.h:5514
QCPItemEllipse::aiCenter
@ aiCenter
Definition: qcustomplot.h:6726
QCPPaintBufferPixmap::startPainting
virtual QCPPainter * startPainting() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:678
QCPAxis::mTickVectorLabels
QVector< QString > mTickVectorLabels
Definition: qcustomplot.h:2341
QCustomPlot::mOpenGlCacheLabelsBackup
bool mOpenGlCacheLabelsBackup
Definition: qcustomplot.h:3970
QCPLayout::elementAt
virtual QCPLayoutElement * elementAt(int index) const =0
QCP::iSelectAxes
@ iSelectAxes
0x010 Axes are selectable (or parts of them, see QCPAxis::setSelectableParts)
Definition: qcustomplot.h:277
QCPAxisTickerLog::mLogBase
double mLogBase
Definition: qcustomplot.h:2017
QCPPolarAxisRadial::setAngle
void setAngle(double degrees)
Definition: qcustomplot.cpp:31403
QCPPolarAxisRadial::setSelectableParts
Q_SLOT void setSelectableParts(const QCPPolarAxisRadial::SelectableParts &selectableParts)
Definition: qcustomplot.cpp:31262
QCPLayoutInset::InsetPlacement
InsetPlacement
Definition: qcustomplot.h:1444
QCPAxisPainterPrivate::CachedLabel
Definition: qcustomplot.h:2431
QCPLabelPainterPrivate::setAnchorMode
void setAnchorMode(AnchorMode mode)
Definition: qcustomplot.cpp:5509
QCustomPlot::layerCount
int layerCount() const
Definition: qcustomplot.cpp:14743
QCPItemTracer::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:30443
QCPItemPixmap::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:30357
QCPPolarAxisAngular::angle
double angle() const
Definition: qcustomplot.h:7263
QCPItemRect::mBrush
QBrush mBrush
Definition: qcustomplot.h:6571
QCPBarsGroup::spacingType
SpacingType spacingType() const
Definition: qcustomplot.h:5704
QCPColorGradient::gpHot
@ gpHot
Continuous lightness from black over firey colors to white (suited for non-biased data representation...
Definition: qcustomplot.h:4747
QCPSelectionDecorator::pen
QPen pen() const
Definition: qcustomplot.h:3419
QCPAxis::lowerEnding
QCPLineEnding lowerEnding() const
Definition: qcustomplot.cpp:8340
QCPAbstractLegendItem::font
QFont font() const
Definition: qcustomplot.h:5030
QCPFinancial::addData
void addData(const QVector< double > &keys, const QVector< double > &open, const QVector< double > &high, const QVector< double > &low, const QVector< double > &close, bool alreadySorted=false)
Definition: qcustomplot.cpp:27235
QCPColorGradient::gpHues
@ gpHues
Full hue cycle, with highest and lowest color red (suitable for periodic data, such as angles and pha...
Definition: qcustomplot.h:4757
QCPPolarLegendItem::getTextColor
QColor getTextColor() const
Definition: qcustomplot.cpp:34382
QCPGrid::pen
QPen pen() const
Definition: qcustomplot.h:2052
QCPStatisticalBox::outlierStyle
QCPScatterStyle outlierStyle() const
Definition: qcustomplot.h:5930
QCPColorScale::QCPColorScale
QCPColorScale(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:20108
QCPAxisTickerText::mTicks
QMap< double, QString > mTicks
Definition: qcustomplot.h:1927
QCPAxisTickerDateTime::dsNone
@ dsNone
Definition: qcustomplot.h:1796
QCPAbstractLegendItem::selectionChanged
void selectionChanged(bool selected)
Definition: moc_qcustomplot.cpp:4436
QCPAxisTickerFixed::QCPAxisTickerFixed
QCPAxisTickerFixed()
Definition: qcustomplot.cpp:7112
QCPPolarAxisRadial::lmRotated
@ lmRotated
Definition: qcustomplot.h:7006
QCPBarsGroup::mBars
QList< QCPBars * > mBars
Definition: qcustomplot.h:5727
QCPItemEllipse::~QCPItemEllipse
virtual ~QCPItemEllipse() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29949
QCPBars::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24705
QCPPolarAxisRadial::QCPPolarAxisRadial
QCPPolarAxisRadial(QCPPolarAxisAngular *parent)
Definition: qcustomplot.cpp:31064
QCPLayoutGrid::fillOrder
FillOrder fillOrder() const
Definition: qcustomplot.h:1384
QCPAbstractPlottable::valueAxis
QCPAxis * valueAxis() const
Definition: qcustomplot.h:3484
QCPSelectionRect::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:2978
QCPPainter::modes
PainterModes modes() const
Definition: qcustomplot.h:502
QCPItemBracket::pen
QPen pen() const
Definition: qcustomplot.h:6929
QCPColorGradient::mPeriodic
bool mPeriodic
Definition: qcustomplot.h:4798
QCPAbstractPlottable::setName
void setName(const QString &name)
Definition: qcustomplot.cpp:11448
QCPAxis::scaleRange
void scaleRange(double factor)
Definition: qcustomplot.cpp:9136
QCPBars::getVisibleDataBounds
void getVisibleDataBounds(QCPBarsDataContainer::const_iterator &begin, QCPBarsDataContainer::const_iterator &end) const
Definition: qcustomplot.cpp:24881
QCPPolarAxisAngular::getBasePen
QPen getBasePen() const
Definition: qcustomplot.cpp:33879
QCPFinancial::csCandlestick
@ csCandlestick
Candlestick representation.
Definition: qcustomplot.h:6184
QCPBars::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24675
QCPAbstractItem::createPosition
QCPItemPosition * createPosition(const QString &name)
Definition: qcustomplot.cpp:13186
QCPColorMap::mMapImage
QImage mMapImage
Definition: qcustomplot.h:6100
QCPPolarAxisAngular::lmUpright
@ lmUpright
Definition: qcustomplot.h:7244
QCPPolarAxisRadial::setupTickVectors
void setupTickVectors()
Definition: qcustomplot.cpp:32349
QCPLayoutElement::setOuterRect
void setOuterRect(const QRect &rect)
Definition: qcustomplot.cpp:3240
QCPLayerable::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const
Definition: qcustomplot.cpp:1503
QCP::phCacheLabels
@ phCacheLabels
0x004 axis (tick) labels will be cached as pixmaps, increasing replot performance.
Definition: qcustomplot.h:261
QCP::srmSelect
@ srmSelect
When dragging the mouse, a selection rect becomes active. Upon releasing, plottable data points that ...
Definition: qcustomplot.h:292
QCPPolarAxisRadial::setSubTickPen
void setSubTickPen(const QPen &pen)
Definition: qcustomplot.cpp:31745
QCPAxis::axisRect
QCPAxisRect * axisRect() const
Definition: qcustomplot.h:2181
QCPItemBracket::mPen
QPen mPen
Definition: qcustomplot.h:6950
QCPPolarAxisRadial::mSelectableParts
SelectableParts mSelectableParts
Definition: qcustomplot.h:7138
QCPItemAnchor::removeChildX
void removeChildX(QCPItemPosition *pos)
Definition: qcustomplot.cpp:12108
QCPLayoutGrid::mColumnSpacing
int mColumnSpacing
Definition: qcustomplot.h:1423
QCPItemTracer::updatePosition
void updatePosition()
Definition: qcustomplot.cpp:30662
QCPPolarAxisAngular::ticker
QSharedPointer< QCPAxisTicker > ticker() const
Definition: qcustomplot.h:7264
QCPAxisPainterPrivate::mLabelCache
QCache< QString, CachedLabel > mLabelCache
Definition: qcustomplot.h:2444
QCPErrorBarsData
Holds the data of one single error bar for QCPErrorBars.
Definition: qcustomplot.h:6260
QCPPolarAxisRadial::subTickLengthOut
int subTickLengthOut() const
Definition: qcustomplot.cpp:31174
QCPBars::getStackedBaseValue
double getStackedBaseValue(double key, bool positive) const
Definition: qcustomplot.cpp:25028
QCPPolarGrid::type
GridTypes type() const
Definition: qcustomplot.h:7517
QCPPolarAxisRadial::selectionChanged
void selectionChanged(const QCPPolarAxisRadial::SelectableParts &parts)
Definition: moc_qcustomplot.cpp:8300
QCPLegend::setSelectedBrush
void setSelectedBrush(const QBrush &brush)
Definition: qcustomplot.cpp:19291
QCPAxisTickerTime::mTimeFormat
QString mTimeFormat
Definition: qcustomplot.h:1840
QCPColorGradient::gpGeography
@ gpGeography
Colors suitable to represent different elevations on geographical maps.
Definition: qcustomplot.h:4751
QCPAbstractPlottable::rescaleAxes
void rescaleAxes(bool onlyEnlarge=false) const
Definition: qcustomplot.cpp:11706
QCPItemCurve::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:29296
QCPPolarAxisAngular::setupTickVectors
void setupTickVectors()
Definition: qcustomplot.cpp:33851
QCustomPlot::QCPGraph
friend class QCPGraph
Definition: qcustomplot.h:4016
QCPItemText::mainFont
QFont mainFont() const
Definition: qcustomplot.cpp:29868
QCPLayoutGrid::QCPLayoutGrid
QCPLayoutGrid()
Definition: qcustomplot.cpp:4104
QCPGrid::QCPGrid
QCPGrid(QCPAxis *parentAxis)
Definition: qcustomplot.cpp:7855
QCPLineEnding::mStyle
EndingStyle mStyle
Definition: qcustomplot.h:1544
QCPPolarAxisAngular::mSelectedParts
SelectableParts mSelectedParts
Definition: qcustomplot.h:7411
QCPMarginGroup::clear
void clear()
Definition: qcustomplot.cpp:3076
QCPItemAnchor::QCPItemAnchor
QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name, int anchorId=-1)
Definition: qcustomplot.cpp:12038
QCPLayoutGrid::foRowsFirst
@ foRowsFirst
Rows are filled first, and a new element is wrapped to the next column if the row count would exceed ...
Definition: qcustomplot.h:1368
QCPSelectionRect::QCPSelectionRect
QCPSelectionRect(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:2846
QCPPolarGraph::mPen
QPen mPen
Definition: qcustomplot.h:7687
QCPItemPixmap::mScaledPixmapInvalidated
bool mScaledPixmapInvalidated
Definition: qcustomplot.h:6795
QCPAxisRect::wheelEvent
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18642
QCPPolarGraph::applyFillAntialiasingHint
void applyFillAntialiasingHint(QCPPainter *painter) const
Definition: qcustomplot.cpp:35144
QCPColorMapData::clear
void clear()
Definition: qcustomplot.cpp:26147
QCPAxis::mCachedMarginValid
bool mCachedMarginValid
Definition: qcustomplot.h:2343
QCPPolarAxisAngular::mTickLengthOut
int mTickLengthOut
Definition: qcustomplot.h:7431
QCPAxis::graphs
QList< QCPGraph * > graphs() const
Definition: qcustomplot.cpp:9410
QCPPolarAxisAngular::~QCPPolarAxisAngular
virtual ~QCPPolarAxisAngular()
Definition: qcustomplot.cpp:32621
QCPAxis::orientation
Qt::Orientation orientation() const
Definition: qcustomplot.h:2274
QCPPolarGraph::selectableChanged
void selectableChanged(QCP::SelectionType selectable)
Definition: moc_qcustomplot.cpp:8895
QCPLegend::removeItem
bool removeItem(int index)
Definition: qcustomplot.cpp:19431
QCPSelectionDecoratorBracket::setBracketPen
void setBracketPen(const QPen &pen)
Definition: qcustomplot.cpp:17163
QCPPolarAxisRadial::mSelectedBasePen
QPen mSelectedBasePen
Definition: qcustomplot.h:7139
QCPLayoutElement::minimumMargins
QMargins minimumMargins() const
Definition: qcustomplot.h:1248
QCPErrorBars::data
QSharedPointer< QCPErrorBarsDataContainer > data() const
Definition: qcustomplot.h:6315
QCPTextElement::mainTextColor
QColor mainTextColor() const
Definition: qcustomplot.cpp:20011
QCPLegend::setSelectableParts
Q_SLOT void setSelectableParts(const SelectableParts &selectableParts)
Definition: qcustomplot.cpp:19209
QCPItemEllipse::anchorPixelPosition
virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30052
QCPColorMap::gradientChanged
void gradientChanged(const QCPColorGradient &newGradient)
Definition: moc_qcustomplot.cpp:6456
QCPPolarAxisAngular::spAxisLabel
@ spAxisLabel
The axis label.
Definition: qcustomplot.h:7235
QCPAxisTickerText::addTicks
void addTicks(const QMap< double, QString > &ticks)
Definition: qcustomplot.cpp:7308
QCPAxis::mPadding
int mPadding
Definition: qcustomplot.h:2305
QCPAbstractPlottable::setAntialiasedScatters
void setAntialiasedScatters(bool enabled)
Definition: qcustomplot.cpp:11470
QCPColorScale::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20511
QCPItemCurve::QCPItemCurve
QCPItemCurve(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:29261
QCPAxisPainterPrivate::tickLabelSide
QCPAxis::LabelSide tickLabelSide
Definition: qcustomplot.h:2414
QCPColorScaleAxisRectPrivate::mGradientImageInvalidated
bool mGradientImageInvalidated
Definition: qcustomplot.h:5327
QCPPolarGrid
The grid in both angular and radial dimensions for polar plots.
Definition: qcustomplot.h:7494
QCustomPlot::mCurrentLayer
QCPLayer * mCurrentLayer
Definition: qcustomplot.h:3950
QCPAbstractLegendItem::mSelectable
bool mSelectable
Definition: qcustomplot.h:5059
QCPColorGradient::updateColorBuffer
void updateColorBuffer()
Definition: qcustomplot.cpp:17009
QCPAbstractItem::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:13256
QCP::MarginSide
MarginSide
Definition: qcustomplot.h:217
QCPPolarAxisRadial::stLinear
@ stLinear
Linear scaling.
Definition: qcustomplot.h:6988
QCPLegend::selectedIconBorderPen
QPen selectedIconBorderPen() const
Definition: qcustomplot.h:5148
QCPAbstractPaintBuffer::mInvalidated
bool mInvalidated
Definition: qcustomplot.h:567
QCPDataSelection::dataRanges
QList< QCPDataRange > dataRanges() const
Definition: qcustomplot.h:976
QCPAxisTicker::setTickOrigin
void setTickOrigin(double origin)
Definition: qcustomplot.cpp:6164
QCPColorMap::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:26655
QCP::aeAxes
@ aeAxes
0x0001 Axis base line and tick marks
Definition: qcustomplot.h:235
QCPItemText::mTextAlignment
Qt::Alignment mTextAlignment
Definition: qcustomplot.h:6663
QCPAxisRect::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18016
QCPAxisTicker::setTickCount
void setTickCount(int count)
Definition: qcustomplot.cpp:6148
QCPAbstractLegendItem::selected
bool selected() const
Definition: qcustomplot.h:5035
QCPItemPosition::valueAxis
QCPAxis * valueAxis() const
Definition: qcustomplot.h:3641
QCPLayoutElement
The abstract base class for all objects that form the layout system.
Definition: qcustomplot.h:1203
QCPStatisticalBox::width
double width() const
Definition: qcustomplot.h:5924
QCPPolarGraph::brush
QBrush brush() const
Definition: qcustomplot.h:7625
QCustomPlot::mBufferDevicePixelRatio
double mBufferDevicePixelRatio
Definition: qcustomplot.h:3934
QCustomPlot::selectionRect
QCPSelectionRect * selectionRect() const
Definition: qcustomplot.h:3810
QCPAxisRect::rangeZoom
Qt::Orientations rangeZoom() const
Definition: qcustomplot.h:4907
QCPPolarAxisAngular::moveRange
void moveRange(double diff)
Definition: qcustomplot.cpp:32776
QCPErrorBars::dataMainKey
virtual double dataMainKey(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28158
QCPSelectionDecoratorBracket::mBracketStyle
BracketStyle mBracketStyle
Definition: qcustomplot.h:4870
QCPAxis::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9558
QCPAbstractPlottable::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:11978
QCPAxis::setRangeLower
void setRangeLower(double lower)
Definition: qcustomplot.cpp:8500
QCustomPlot::removeItem
bool removeItem(QCPAbstractItem *item)
Definition: qcustomplot.cpp:14558
QCPAxis::getLabelColor
QColor getLabelColor() const
Definition: qcustomplot.cpp:9805
QCPPolarAxisAngular::setTickLengthIn
void setTickLengthIn(int inside)
Definition: qcustomplot.cpp:33550
QCPAxisTicker::setTickStepStrategy
void setTickStepStrategy(TickStepStrategy strategy)
Definition: qcustomplot.cpp:6135
QCPAxisRect::plottables
QList< QCPAbstractPlottable * > plottables() const
Definition: qcustomplot.cpp:17894
QCustomPlot::wheelEvent
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15690
QCPAxisRect::drawBackground
void drawBackground(QCPPainter *painter)
Definition: qcustomplot.cpp:18418
QCPBarsGroup::unregisterBars
void unregisterBars(QCPBars *bars)
Definition: qcustomplot.cpp:24142
QCPItemTracer::tsCrosshair
@ tsCrosshair
A plus shaped crosshair which spans the complete axis rect.
Definition: qcustomplot.h:6838
QCPScatterStyle::undefinePen
void undefinePen()
Definition: qcustomplot.cpp:10847
QCustomPlot::setInteraction
void setInteraction(const QCP::Interaction &interaction, bool enabled=true)
Definition: qcustomplot.cpp:13876
QCPBars::baseValue
double baseValue() const
Definition: qcustomplot.h:5808
QCPAxisTickerPi::fsAsciiFractions
@ fsAsciiFractions
Fractions are written as rationals using ASCII characters only, e.g. "1/4" or "1/8".
Definition: qcustomplot.h:1953
QCPAxis::setTickLengthOut
void setTickLengthOut(int outside)
Definition: qcustomplot.cpp:8814
QCPPolarGraph::rescaleValueAxis
void rescaleValueAxis(bool onlyEnlarge=false, bool inKeyRange=false) const
Definition: qcustomplot.cpp:34795
QCPColorScale::mDataRange
QCPRange mDataRange
Definition: qcustomplot.h:5396
QCPDataSelection
Describes a data set by holding multiple QCPDataRange instances.
Definition: qcustomplot.h:951
QCPAxisTickerTime::tuDays
@ tuDays
Days (%d in setTimeFormat)
Definition: qcustomplot.h:1824
QCPLayoutElement::maximumSize
QSize maximumSize() const
Definition: qcustomplot.h:1251
QCPLegend::setTextColor
void setTextColor(const QColor &color)
Definition: qcustomplot.cpp:19151
QCustomPlot::setPlottingHint
void setPlottingHint(QCP::PlottingHint hint, bool enabled=true)
Definition: qcustomplot.cpp:13931
QCPLabelPainterPrivate::LabelData::rotation
double rotation
Definition: qcustomplot.h:1642
QCPSelectionDecorator::mScatterStyle
QCPScatterStyle mScatterStyle
Definition: qcustomplot.h:3443
QCPLegend::mBrush
QBrush mBrush
Definition: qcustomplot.h:5192
QCPAxisTickerPi::setPiSymbol
void setPiSymbol(QString symbol)
Definition: qcustomplot.cpp:7444
QCPLegend::setBorderPen
void setBorderPen(const QPen &pen)
Definition: qcustomplot.cpp:19110
QCPMarginGroup::isEmpty
bool isEmpty() const
Definition: qcustomplot.cpp:3060
QCPPolarAxisRadial::setSelectedBasePen
void setSelectedBasePen(const QPen &pen)
Definition: qcustomplot.cpp:31854
QCustomPlot::setupPaintBuffers
void setupPaintBuffers()
Definition: qcustomplot.cpp:15820
QCPLabelPainterPrivate::rotationCorrectedSide
AnchorSide rotationCorrectedSide(AnchorSide side, double rotation) const
Definition: qcustomplot.cpp:6018
QCPPolarAxisRadial::ScaleType
ScaleType
Definition: qcustomplot.h:6988
QCPLayoutElement::minimumSize
QSize minimumSize() const
Definition: qcustomplot.h:1250
QCPLabelPainterPrivate::setSubstituteExponent
void setSubstituteExponent(bool enabled)
Definition: qcustomplot.cpp:5548
QCPLayer::setVisible
void setVisible(bool visible)
Definition: qcustomplot.cpp:1101
QCustomPlot::mPaintBuffers
QList< QSharedPointer< QCPAbstractPaintBuffer > > mPaintBuffers
Definition: qcustomplot.h:3958
QCPColorMap::~QCPColorMap
virtual ~QCPColorMap() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:26419
QCPPolarGraph::drawFill
virtual void drawFill(QCPPainter *painter, QVector< QPointF > *lines) const
Definition: qcustomplot.cpp:35088
QCPLayoutInset::mInsetRect
QList< QRectF > mInsetRect
Definition: qcustomplot.h:1480
QCPGraph::lsLine
@ lsLine
data points are connected by a straight line
Definition: qcustomplot.h:5475
QCPStatisticalBox::mWidth
double mWidth
Definition: qcustomplot.h:5955
QCPSelectionDecoratorBracket::mBracketBrush
QBrush mBracketBrush
Definition: qcustomplot.h:4867
QCPAxis::setNumberPrecision
void setNumberPrecision(int precision)
Definition: qcustomplot.cpp:8770
QCPItemPosition::setAxisRect
void setAxisRect(QCPAxisRect *axisRect)
Definition: qcustomplot.cpp:12647
QCPBars::mWidthType
WidthType mWidthType
Definition: qcustomplot.h:5839
QCPPolarAxisRadial::getTickPen
QPen getTickPen() const
Definition: qcustomplot.cpp:32372
QCPItemText::text
QString text() const
Definition: qcustomplot.h:6619
QCPPainter::begin
bool begin(QPaintDevice *device)
Definition: qcustomplot.cpp:421
QCP::SelectionRectMode
SelectionRectMode
Definition: qcustomplot.h:290
QCPItemPixmap::aiTop
@ aiTop
Definition: qcustomplot.h:6789
QCPSelectionDecorator
Controls how a plottable's data selection is drawn.
Definition: qcustomplot.h:3411
QCPLayer::children
QList< QCPLayerable * > children() const
Definition: qcustomplot.h:679
QCPRange::maxRange
static const double maxRange
Definition: qcustomplot.h:833
QCPPolarAxisRadial::updateGeometry
void updateGeometry(const QPointF &center, double radius)
Definition: qcustomplot.cpp:32263
QCPScatterStyle::ssPlusCircle
@ ssPlusCircle
\enumimage{ssPlusCircle.png} a circle with a plus inside
Definition: qcustomplot.h:2506
QCPColorGradient::gpSpectrum
@ gpSpectrum
An approximation of the visible light spectrum (creates banding illusion but allows more precise magn...
Definition: qcustomplot.h:4755
QCPItemLine::~QCPItemLine
virtual ~QCPItemLine() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29035
QCPStatisticalBox::setMedianPen
void setMedianPen(const QPen &pen)
Definition: qcustomplot.cpp:25410
QCPItemCurve::head
QCPLineEnding head() const
Definition: qcustomplot.h:6494
QCPLayerable::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details)
Definition: qcustomplot.cpp:1740
QCPItemCurve::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:29393
QCPAxisPainterPrivate::mTickLabelsSelectionBox
QRect mTickLabelsSelectionBox
Definition: qcustomplot.h:2445
QCPItemPixmap::updateScaledPixmap
void updateScaledPixmap(QRect finalRect=QRect(), bool flipHorz=false, bool flipVert=false)
Definition: qcustomplot.cpp:30262
QCPPolarAxisAngular::removeRadialAxis
bool removeRadialAxis(QCPPolarAxisRadial *axis)
Definition: qcustomplot.cpp:32750
QCPLayerable::mouseDoubleClickEvent
virtual void mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details)
Definition: qcustomplot.cpp:1808
QCPCurve::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:22865
QCPLayerable::parentPlot
QCustomPlot * parentPlot() const
Definition: qcustomplot.h:732
QCPAxis::setNumberFormat
void setNumberFormat(const QString &formatCode)
Definition: qcustomplot.cpp:8710
QCPDataSelection::simplify
void simplify()
Definition: qcustomplot.cpp:2600
QCPItemPosition::ptPlotCoords
@ ptPlotCoords
Dynamic positioning at a plot coordinate defined by two axes (see setAxes).
Definition: qcustomplot.h:3623
QCPAxisTicker::getMantissa
double getMantissa(double input, double *magnitude=nullptr) const
Definition: qcustomplot.cpp:6439
QCPAbstractPlottable::rescaleValueAxis
void rescaleValueAxis(bool onlyEnlarge=false, bool inKeyRange=false) const
Definition: qcustomplot.cpp:11759
QCPAbstractPlottable::QCPPlottableLegendItem
friend class QCPPlottableLegendItem
Definition: qcustomplot.h:3558
QCPItemBracket::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:30968
QCPLabelPainterPrivate::LabelData::expFont
QFont expFont
Definition: qcustomplot.h:1648
QCPPolarAxisAngular::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32916
QCPAxisRect::update
virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:17972
QCPAxisRect::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18524
QCPPolarAxisRadial::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32182
QCPItemTracer::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6879
QCPItemRect::aiBottom
@ aiBottom
Definition: qcustomplot.h:6567
QCPTextElement::setTextColor
void setTextColor(const QColor &color)
Definition: qcustomplot.cpp:19823
QCPScatterStyle::mShape
ScatterShape mShape
Definition: qcustomplot.h:2549
QCPLayer::LayerMode
LayerMode
Definition: qcustomplot.h:667
QCPItemText::setFont
void setFont(const QFont &font)
Definition: qcustomplot.cpp:29679
QCPLayoutGrid::getMinimumRowColSizes
void getMinimumRowColSizes(QVector< int > *minColWidths, QVector< int > *minRowHeights) const
Definition: qcustomplot.cpp:4799
QCPAxisRect::axisCount
int axisCount(QCPAxis::AxisType type) const
Definition: qcustomplot.cpp:17594
QCPAxis::scaleTypeChanged
void scaleTypeChanged(QCPAxis::ScaleType scaleType)
Definition: moc_qcustomplot.cpp:2486
QCPPolarAxisRadial::ticker
QSharedPointer< QCPAxisTicker > ticker() const
Definition: qcustomplot.h:7024
QCustomPlot::mMouseEventLayerable
QPointer< QCPLayerable > mMouseEventLayerable
Definition: qcustomplot.h:3961
QCPTextElement::selectableChanged
void selectableChanged(bool selectable)
Definition: moc_qcustomplot.cpp:5031
QCPSelectionDecorator::mBrush
QBrush mBrush
Definition: qcustomplot.h:3442
QCPLayout::take
virtual bool take(QCPLayoutElement *element)=0
QCPAxisPainterPrivate::axisSelectionBox
QRect axisSelectionBox() const
Definition: qcustomplot.h:2400
QCPColorScaleAxisRectPrivate::mParentColorScale
QCPColorScale * mParentColorScale
Definition: qcustomplot.h:5325
QCPAbstractPlottable::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:11497
QCP::SelectionType
SelectionType
Definition: qcustomplot.h:314
QCPAxisPainterPrivate::TickLabelData::expFont
QFont expFont
Definition: qcustomplot.h:2440
QCPColorGradient::gpNight
@ gpNight
Continuous lightness from black over weak blueish colors to white (suited for non-biased data represe...
Definition: qcustomplot.h:4749
QCPLegend::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19579
QCPLegend::itemWithPlottable
QCPPlottableLegendItem * itemWithPlottable(const QCPAbstractPlottable *plottable) const
Definition: qcustomplot.cpp:19349
QCPPolarAxisAngular::mSelectedTickLabelColor
QColor mSelectedTickLabelColor
Definition: qcustomplot.h:7423
QCPStatisticalBox::setData
void setData(QSharedPointer< QCPStatisticalBoxDataContainer > data)
Definition: qcustomplot.cpp:25322
QCPDataRange::intersects
bool intersects(const QCPDataRange &other) const
Definition: qcustomplot.cpp:2328
QCPPolarGraph::QCPPolarLegendItem
friend class QCPPolarLegendItem
Definition: qcustomplot.h:7730
QCPAxis::tickLabelSide
LabelSide tickLabelSide() const
Definition: qcustomplot.cpp:8284
QCustomPlot::clearItems
int clearItems()
Definition: qcustomplot.cpp:14594
QCPPolarAxisRadial::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32220
QCPItemCurve::mPen
QPen mPen
Definition: qcustomplot.h:6513
QCPAxisTickerLog::QCPAxisTickerLog
QCPAxisTickerLog()
Definition: qcustomplot.cpp:7724
QCPBars::widthType
WidthType widthType() const
Definition: qcustomplot.h:5806
QCPAxisPainterPrivate::mLabelParameterHash
QByteArray mLabelParameterHash
Definition: qcustomplot.h:2443
QCPPolarGrid::gtAll
@ gtAll
Definition: qcustomplot.h:7506
QCPAbstractLegendItem::selectable
bool selectable() const
Definition: qcustomplot.h:5034
QCPPolarGraph::mAntialiasedFill
bool mAntialiasedFill
Definition: qcustomplot.h:7686
QCPLayoutElement::autoMargins
QCP::MarginSides autoMargins() const
Definition: qcustomplot.h:1249
QCPLayer::draw
void draw(QCPPainter *painter)
Definition: qcustomplot.cpp:1143
QCPLayoutInset::elementCount
virtual int elementCount() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:5033
QCPAbstractLegendItem::clipRect
virtual QRect clipRect() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18841
QCustomPlot::mNotAntialiasedElements
QCP::AntialiasedElements mNotAntialiasedElements
Definition: qcustomplot.h:3941
QCPAxis::plottables
QList< QCPAbstractPlottable * > plottables() const
Definition: qcustomplot.cpp:9392
QCPFinancial::getVisibleDataBounds
void getVisibleDataBounds(QCPFinancialDataContainer::const_iterator &begin, QCPFinancialDataContainer::const_iterator &end) const
Definition: qcustomplot.cpp:27815
QCPSelectionRect::mBrush
QBrush mBrush
Definition: qcustomplot.h:1149
QCPLegend::selectedItems
QList< QCPAbstractLegendItem * > selectedItems() const
Definition: qcustomplot.cpp:19482
QCPPolarAxisRadial::setRangeLower
void setRangeLower(double lower)
Definition: qcustomplot.cpp:31349
QCPBars::dataPixelPosition
virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24784
QCPAxisPainterPrivate::~QCPAxisPainterPrivate
virtual ~QCPAxisPainterPrivate()
Definition: qcustomplot.cpp:9919
QCPAxisRect::zoom
void zoom(const QRectF &pixelRect)
Definition: qcustomplot.cpp:17781
QCPPolarAxisAngular::mRangeReversed
bool mRangeReversed
Definition: qcustomplot.h:7436
QCPPolarAxisAngular::registerPolarGraph
bool registerPolarGraph(QCPPolarGraph *graph)
Definition: qcustomplot.cpp:34103
QCPPolarAxisRadial::setRangeDrag
void setRangeDrag(bool enabled)
Definition: qcustomplot.cpp:31185
QCPPolarGraph::getDataSegments
void getDataSegments(QList< QCPDataRange > &selectedSegments, QList< QCPDataRange > &unselectedSegments) const
Definition: qcustomplot.cpp:35206
QCPDataRange::intersection
QCPDataRange intersection(const QCPDataRange &other) const
Definition: qcustomplot.cpp:2314
QCPLabelPainterPrivate::getAnchorPos
QPointF getAnchorPos(const QPointF &tickPos)
Definition: qcustomplot.cpp:5744
QCPGraph::dataToStepCenterLines
QVector< QPointF > dataToStepCenterLines(const QVector< QCPGraphData > &data) const
Definition: qcustomplot.cpp:21459
QCPPolarAxisRadial::range
const QCPRange range() const
Definition: qcustomplot.h:7020
QCPItemPixmap::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6798
QCPItemRect::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:29450
QCPPolarGraph::setAntialiasedScatters
void setAntialiasedScatters(bool enabled)
Definition: qcustomplot.cpp:34486
QCPAxisTickerText::setTicks
void setTicks(const QMap< double, QString > &ticks)
Definition: qcustomplot.cpp:7242
QCPPolarAxisAngular
The main container for polar plots, representing the angular axis as a circle.
Definition: qcustomplot.h:7221
QCPGrid::drawGridLines
void drawGridLines(QCPPainter *painter) const
Definition: qcustomplot.cpp:7964
QCPAxis::tickLabelPadding
int tickLabelPadding() const
Definition: qcustomplot.cpp:8272
QCPAxisRect::addAxis
QCPAxis * addAxis(QCPAxis::AxisType type, QCPAxis *axis=nullptr)
Definition: qcustomplot.cpp:17675
QCPPolarAxisRadial::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32109
QCPPolarGrid::gtRadial
@ gtRadial
Definition: qcustomplot.h:7505
QCustomPlot::mBackgroundScaled
bool mBackgroundScaled
Definition: qcustomplot.h:3948
QCPAxis::upperEnding
QCPLineEnding upperEnding() const
Definition: qcustomplot.cpp:8346
QCPLayer::~QCPLayer
virtual ~QCPLayer()
Definition: qcustomplot.cpp:1079
QCPLineEnding::width
double width() const
Definition: qcustomplot.h:1526
QCPTextElement::setTextFlags
void setTextFlags(int flags)
Definition: qcustomplot.cpp:19803
QCPLegend::hasItem
bool hasItem(QCPAbstractLegendItem *item) const
Definition: qcustomplot.cpp:19382
QCPItemTracer::pen
QPen pen() const
Definition: qcustomplot.h:6848
QCPPolarAxisAngular::mTickVectorCosSin
QVector< QPointF > mTickVectorCosSin
Definition: qcustomplot.h:7447
QCPItemBracket::length
double length() const
Definition: qcustomplot.h:6931
QCPStatisticalBox::setWidth
void setWidth(double width)
Definition: qcustomplot.cpp:25348
QCPPolarAxisRadial::setScaleType
Q_SLOT void setScaleType(QCPPolarAxisRadial::ScaleType type)
Definition: qcustomplot.cpp:31214
QCPPolarGrid::setRadialPen
void setRadialPen(const QPen &pen)
Definition: qcustomplot.cpp:34217
QCPGraph::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:21175
QCPColorMapData::mValueRange
QCPRange mValueRange
Definition: qcustomplot.h:6027
QCPBarsGroup::append
void append(QCPBars *bars)
Definition: qcustomplot.cpp:24065
QCPPolarGraph::LineStyle
LineStyle
Definition: qcustomplot.h:7611
QCustomPlot::autoAddPlottableToLegend
bool autoAddPlottableToLegend() const
Definition: qcustomplot.h:3803
QCPLabelPainterPrivate::mLetterDescent
int mLetterDescent
Definition: qcustomplot.h:1669
QCPPolarAxisRadial::getSubTickPen
QPen getSubTickPen() const
Definition: qcustomplot.cpp:32382
QCPAxisPainterPrivate::label
QString label
Definition: qcustomplot.h:2411
QCPAxisTickerFixed::ScaleStrategy
ScaleStrategy
Definition: qcustomplot.h:1873
QCPTextElement::mouseDoubleClickEvent
virtual void mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19990
QCPPolarAxisRadial::mScaleType
ScaleType mScaleType
Definition: qcustomplot.h:7164
QCPAbstractLegendItem::setSelectable
Q_SLOT void setSelectable(bool selectable)
Definition: qcustomplot.cpp:18794
QCPPolarGraph::setLineStyle
void setLineStyle(LineStyle ls)
Definition: qcustomplot.cpp:34653
QCPAxis::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9483
QCustomPlot::mOpenGl
bool mOpenGl
Definition: qcustomplot.h:3955
QCPLabelPainterPrivate::setMultiplicationSymbol
void setMultiplicationSymbol(QChar symbol)
Definition: qcustomplot.cpp:5553
QCPItemAnchor::mAnchorId
int mAnchorId
Definition: qcustomplot.h:3586
QCPItemCurve::tail
QCPLineEnding tail() const
Definition: qcustomplot.h:6495
QCustomPlot::axisRectAt
QCPAxisRect * axisRectAt(const QPointF &pos) const
Definition: qcustomplot.cpp:14991
QCustomPlot::~QCustomPlot
virtual ~QCustomPlot() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:13692
QCPAxis::setTickLengthIn
void setTickLengthIn(int inside)
Definition: qcustomplot.cpp:8799
QCPAxis::rangeReversed
bool rangeReversed() const
Definition: qcustomplot.h:2184
QCPLayerable::layerChanged
void layerChanged(QCPLayer *newLayer)
Definition: moc_qcustomplot.cpp:680
QCPItemPosition::keyAxis
QCPAxis * keyAxis() const
Definition: qcustomplot.h:3640
QCPErrorBars::symbolGap
double symbolGap() const
Definition: qcustomplot.h:6319
QCPColorMap::updateLegendIcon
Q_SLOT void updateLegendIcon(Qt::TransformationMode transformMode=Qt::SmoothTransformation, const QSize &thumbSize=QSize(32, 18))
Definition: qcustomplot.cpp:26618
QCPItemLine::mHead
QCPLineEnding mHead
Definition: qcustomplot.h:6462
QCPAxisPainterPrivate::mParentPlot
QCustomPlot * mParentPlot
Definition: qcustomplot.h:2442
QCPGraph::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:21095
QCPAxis::lsInside
@ lsInside
Tick labels will be displayed inside the axis rect and clipped to the inner axis rect.
Definition: qcustomplot.h:2151
QCPAbstractPlottable
The abstract base class for all data representing objects in a plot.
Definition: qcustomplot.h:3458
QCPAxisPainterPrivate::subTickPen
QPen subTickPen
Definition: qcustomplot.h:2418
QCPLayer::parentPlot
QCustomPlot * parentPlot() const
Definition: qcustomplot.h:676
QCPAxisPainterPrivate::labelPadding
int labelPadding
Definition: qcustomplot.h:2408
QCPAxis::mAxisPainter
QCPAxisPainterPrivate * mAxisPainter
Definition: qcustomplot.h:2338
QCPDataSelection::dataPointCount
int dataPointCount() const
Definition: qcustomplot.cpp:2528
QCPPlottableLegendItem::QCPPlottableLegendItem
QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable)
Definition: qcustomplot.cpp:18907
QCP::sdBoth
@ sdBoth
Both sign domains, including zero, i.e. all numbers.
Definition: qcustomplot.h:208
QCPPolarAxisAngular::setSubTickLengthOut
void setSubTickLengthOut(int outside)
Definition: qcustomplot.cpp:33625
QCPAxis::mNumberPrecision
int mNumberPrecision
Definition: qcustomplot.h:2321
QCPItemPixmap::getFinalRect
QRect getFinalRect(bool *flippedHorz=nullptr, bool *flippedVert=nullptr) const
Definition: qcustomplot.cpp:30304
QCPAbstractLegendItem::mSelected
bool mSelected
Definition: qcustomplot.h:5059
QCPItemText::mFont
QFont mFont
Definition: qcustomplot.h:6660
QCPPolarAxisAngular::numberFormat
QString numberFormat() const
Definition: qcustomplot.cpp:32646
QCPColorGradient::inverted
QCPColorGradient inverted() const
Definition: qcustomplot.cpp:16980
QCPPolarAxisRadial::setSelectedLabelFont
void setSelectedLabelFont(const QFont &font)
Definition: qcustomplot.cpp:31820
QCPLayoutInset::setInsetPlacement
void setInsetPlacement(int index, InsetPlacement placement)
Definition: qcustomplot.cpp:4951
QCPItemTracer::mBrush
QBrush mBrush
Definition: qcustomplot.h:6880
QCPPainter::drawLine
void drawLine(const QLineF &line)
Definition: qcustomplot.cpp:371
QCPGrid::setSubGridVisible
void setSubGridVisible(bool visible)
Definition: qcustomplot.cpp:7878
QCPLabelPainterPrivate::LabelData::rotatedTotalBounds
QRect rotatedTotalBounds
Definition: qcustomplot.h:1647
QCPAxis::ticker
QSharedPointer< QCPAxisTicker > ticker() const
Definition: qcustomplot.h:2185
QCPGraph
A plottable representing a graph in a plot.
Definition: qcustomplot.h:5457
QCPAxisPainterPrivate::basePen
QPen basePen
Definition: qcustomplot.h:2406
QCPVector2D::operator+=
QCPVector2D & operator+=(const QCPVector2D &vector)
Definition: qcustomplot.cpp:255
QCPColorScale::gradient
QCPColorGradient gradient() const
Definition: qcustomplot.h:5365
QCPLayout::elements
virtual QList< QCPLayoutElement * > elements(bool recursive) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:3697
QCPColorScale::setDataRange
Q_SLOT void setDataRange(const QCPRange &dataRange)
Definition: qcustomplot.cpp:20227
QCPItemTracer::tsNone
@ tsNone
The tracer is not visible.
Definition: qcustomplot.h:6836
QCPTextElement::maximumOuterSizeHint
virtual QSize maximumOuterSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19904
QCPPolarGrid::mAngularPen
QPen mAngularPen
Definition: qcustomplot.h:7544
QCPRange::contains
bool contains(double value) const
Definition: qcustomplot.h:828
QCustomPlot::mAutoAddPlottableToLegend
bool mAutoAddPlottableToLegend
Definition: qcustomplot.h:3936
QCustomPlot::mBackgroundPixmap
QPixmap mBackgroundPixmap
Definition: qcustomplot.h:3946
QCPItemPosition::setParentAnchor
bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false)
Definition: qcustomplot.cpp:12360
QCPItemCurve::pen
QPen pen() const
Definition: qcustomplot.h:6492
QCPAxis::getTickLabelColor
QColor getTickLabelColor() const
Definition: qcustomplot.cpp:9795
QCPItemTracer::mSelectedBrush
QBrush mSelectedBrush
Definition: qcustomplot.h:6880
QCPLayoutElement::setMinimumSize
void setMinimumSize(const QSize &size)
Definition: qcustomplot.cpp:3313
QCPAxis::mSelectedBasePen
QPen mSelectedBasePen
Definition: qcustomplot.h:2308
QCPCurve::pointDistance
double pointDistance(const QPointF &pixelPoint, QCPCurveDataContainer::const_iterator &closestData) const
Definition: qcustomplot.cpp:23870
QCPColorMap::setGradient
Q_SLOT void setGradient(const QCPColorGradient &gradient)
Definition: qcustomplot.cpp:26499
QCPDataRange::setEnd
void setEnd(int end)
Definition: qcustomplot.h:931
QCPAxis::mTickLabels
bool mTickLabels
Definition: qcustomplot.h:2317
QCPErrorBars::errorBarVisible
bool errorBarVisible(int index) const
Definition: qcustomplot.cpp:28773
QCPPolarAxisAngular::setSelectedTickLabelFont
void setSelectedTickLabelFont(const QFont &font)
Definition: qcustomplot.cpp:33720
QCPItemEllipse::QCPItemEllipse
QCPItemEllipse(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:29926
QCPAxis::scaleType
ScaleType scaleType() const
Definition: qcustomplot.h:2182
QCPPolarGraph::setKeyAxis
void setKeyAxis(QCPPolarAxisAngular *axis)
Definition: qcustomplot.cpp:34534
QCPAxisTickerTime::getTickStep
virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:6961
QCPAxisTickerDateTime::getSubTickCount
virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:6678
QCPScatterStyle::ssDot
@ ssDot
\enumimage{ssDot.png} a single pixel (use ssDisc or ssCircle if you want a round shape with a certain...
Definition: qcustomplot.h:2493
QCPPolarAxisAngular::mBackgroundBrush
QBrush mBackgroundBrush
Definition: qcustomplot.h:7399
QCPMarginGroup::elements
QList< QCPLayoutElement * > elements(QCP::MarginSide side) const
Definition: qcustomplot.h:1180
QCPLayoutInset::takeAt
virtual QCPLayoutElement * takeAt(int index) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:5048
QCPSelectionDecoratorBracket::drawDecoration
virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:17290
QCPAxis::setSelectedLabelColor
void setSelectedLabelColor(const QColor &color)
Definition: qcustomplot.cpp:9039
QCPAxis::stLinear
@ stLinear
Linear scaling.
Definition: qcustomplot.h:2159
QCPPolarAxisAngular::mTickLabelFont
QFont mTickLabelFont
Definition: qcustomplot.h:7422
QCPColorScale::mType
QCPAxis::AxisType mType
Definition: qcustomplot.h:5395
QCPItemStraightLine::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:28993
QCP::msRight
@ msRight
0x02 right margin
Definition: qcustomplot.h:218
QCPPainter::setMode
void setMode(PainterMode mode, bool enabled=true)
Definition: qcustomplot.cpp:436
QCPGraph::dataToImpulseLines
QVector< QPointF > dataToImpulseLines(const QVector< QCPGraphData > &data) const
Definition: qcustomplot.cpp:21519
QCPItemPixmap::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30191
QCPSelectionRect::endSelection
virtual void endSelection(QMouseEvent *event)
Definition: qcustomplot.cpp:2944
QCPScatterStyle::ssPlusSquare
@ ssPlusSquare
\enumimage{ssPlusSquare.png} a square with a plus inside
Definition: qcustomplot.h:2504
QCPPolarAxisAngular::mRangeZoom
bool mRangeZoom
Definition: qcustomplot.h:7406
QCPLabelPainterPrivate::QCPLabelPainterPrivate
QCPLabelPainterPrivate(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:5484
QCPPolarAxisAngular::setTickLabelRotation
void setTickLabelRotation(double degrees)
Definition: qcustomplot.cpp:33422
QCPPolarAxisRadial::mSubTickLengthIn
int mSubTickLengthIn
Definition: qcustomplot.h:7158
QCPPainter::save
void save()
Definition: qcustomplot.cpp:452
QCPAbstractPlottable::QCPAbstractPlottable
QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:11414
QCPAxisRect::addAxes
QList< QCPAxis * > addAxes(QCPAxis::AxisTypes types)
Definition: qcustomplot.cpp:17730
QCPPolarAxisAngular::setSelectedBasePen
void setSelectedBasePen(const QPen &pen)
Definition: qcustomplot.cpp:33768
QCPFinancial::mPenNegative
QPen mPenNegative
Definition: qcustomplot.h:6234
QCPAxisRect::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18556
QCPColorGradient::stopsUseAlpha
bool stopsUseAlpha() const
Definition: qcustomplot.cpp:16994
QCPAxisPainterPrivate::type
QCPAxis::AxisType type
Definition: qcustomplot.h:2405
QCPPolarAxisAngular::getPartAt
SelectablePart getPartAt(const QPointF &pos) const
Definition: qcustomplot.cpp:32896
QCPErrorBars::sortKeyIsMainKey
virtual bool sortKeyIsMainKey() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28215
QCPRange
Represents the range an axis is encompassing.
Definition: qcustomplot.h:796
QCPPolarAxisRadial::rangeZoomFactor
double rangeZoomFactor() const
Definition: qcustomplot.h:7016
QCPFinancial::drawOhlcPlot
void drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, bool isSelected)
Definition: qcustomplot.cpp:27511
QCustomPlot::setViewport
void setViewport(const QRect &rect)
Definition: qcustomplot.cpp:14117
QCustomPlot::graph
QCPGraph * graph() const
Definition: qcustomplot.cpp:14402
QCPItemPosition::mValue
double mValue
Definition: qcustomplot.h:3663
QCPBarsGroup::clear
void clear()
Definition: qcustomplot.cpp:24052
QCPLegend::mSelectedFont
QFont mSelectedFont
Definition: qcustomplot.h:5200
QCustomPlot::legendDoubleClick
void legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3902
QCPPolarGrid::setRadialZeroLinePen
void setRadialZeroLinePen(const QPen &pen)
Definition: qcustomplot.cpp:34227
QCustomPlot::setNoAntialiasingOnDrag
void setNoAntialiasingOnDrag(bool enabled)
Definition: qcustomplot.cpp:13911
QCPAbstractLegendItem::mSelectedFont
QFont mSelectedFont
Definition: qcustomplot.h:5057
QCPLayoutElement::mMarginGroups
QHash< QCP::MarginSide, QCPMarginGroup * > mMarginGroups
Definition: qcustomplot.h:1285
QCPScatterStyle::pen
QPen pen() const
Definition: qcustomplot.h:2524
QCPLayer::QCPLayer
QCPLayer(QCustomPlot *parentPlot, const QString &layerName)
Definition: qcustomplot.cpp:1067
QCPFinancial::QCPFinancial
QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:27065
QCustomPlot::setNotAntialiasedElement
void setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled=true)
Definition: qcustomplot.cpp:13787
QCPItemBracket::setStyle
void setStyle(BracketStyle style)
Definition: qcustomplot.cpp:30828
QCPStatisticalBox::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:25507
QCPLabelPainterPrivate::asBottomLeft
@ asBottomLeft
Definition: qcustomplot.h:1588
QCPLayoutGrid::insertColumn
void insertColumn(int newIndex)
Definition: qcustomplot.cpp:4493
QCPPolarAxisRadial::setSelectedTickLabelFont
void setSelectedTickLabelFont(const QFont &font)
Definition: qcustomplot.cpp:31806
QCPItemPosition::parentAnchorY
QCPItemAnchor * parentAnchorY() const
Definition: qcustomplot.h:3636
QCPPolarAxisAngular::setSelectedTickPen
void setSelectedTickPen(const QPen &pen)
Definition: qcustomplot.cpp:33778
QCPLineEnding::esDisc
@ esDisc
A filled circle.
Definition: qcustomplot.h:1512
QCPColorGradient::nhTransparent
@ nhTransparent
NaN data points appear transparent.
Definition: qcustomplot.h:4737
QCPAxis::setSelectedTickPen
void setSelectedTickPen(const QPen &pen)
Definition: qcustomplot.cpp:9059
QCPAxis::setLabelFont
void setLabelFont(const QFont &font)
Definition: qcustomplot.cpp:8918
QCPLayer::replot
void replot()
Definition: qcustomplot.cpp:1198
QCPScatterStyle::spPen
@ spPen
0x01 The pen property, see setPen
Definition: qcustomplot.h:2475
QCPAbstractLegendItem::setSelected
Q_SLOT void setSelected(bool selected)
Definition: qcustomplot.cpp:18811
QCPItemPixmap::anchorPixelPosition
virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30223
QCPLegend::selectedParts
SelectableParts selectedParts() const
Definition: qcustomplot.cpp:19089
QCPLayoutElement::rect
QRect rect() const
Definition: qcustomplot.h:1245
QCPPolarGrid::mAntialiasedZeroLine
bool mAntialiasedZeroLine
Definition: qcustomplot.h:7543
QCPTextElement::mainFont
QFont mainFont() const
Definition: qcustomplot.cpp:20001
QCustomPlot::mouseMove
void mouseMove(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3832
QCPAxis::getTickLabelFont
QFont getTickLabelFont() const
Definition: qcustomplot.cpp:9775
QCPGraph::~QCPGraph
virtual ~QCPGraph() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20878
QCPAbstractItem::hasAnchor
bool hasAnchor(const QString &name) const
Definition: qcustomplot.cpp:13072
QCPPolarAxisAngular::getTickPen
QPen getTickPen() const
Definition: qcustomplot.cpp:33889
QCPScatterStyle::ssDisc
@ ssDisc
\enumimage{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle)
Definition: qcustomplot.h:2497
QCustomPlot::rescaleAxes
Q_SLOT void rescaleAxes(bool onlyVisiblePlottables=false)
Definition: qcustomplot.cpp:15187
QCPScatterStyle::ScatterShape
ScatterShape
Definition: qcustomplot.h:2492
QCPTextElement::setSelected
Q_SLOT void setSelected(bool selected)
Definition: qcustomplot.cpp:19870
QCPPolarGraph::rescaleAxes
void rescaleAxes(bool onlyEnlarge=false) const
Definition: qcustomplot.cpp:34768
QCPFinancialData::QCPFinancialData
QCPFinancialData()
Definition: qcustomplot.cpp:26969
QCPPolarAxisAngular::setSelectedLabelColor
void setSelectedLabelColor(const QColor &color)
Definition: qcustomplot.cpp:33758
QCPColorMap::mTightBoundary
bool mTightBoundary
Definition: qcustomplot.h:6096
QCP::ruDotsPerCentimeter
@ ruDotsPerCentimeter
Resolution is given in dots per centimeter (dpcm)
Definition: qcustomplot.h:187
QCP::epNoCosmetic
@ epNoCosmetic
Cosmetic pens are converted to pens with pixel width 1 when exporting.
Definition: qcustomplot.h:196
QCPItemBracket::bsSquare
@ bsSquare
A brace with angled edges.
Definition: qcustomplot.h:6918
QCPBars::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:24807
QCPPolarGrid::setSubGridType
void setSubGridType(GridTypes type)
Definition: qcustomplot.cpp:34180
QCPItemText::aiLeft
@ aiLeft
Definition: qcustomplot.h:6654
QCPColorMap::setColorScale
void setColorScale(QCPColorScale *colorScale)
Definition: qcustomplot.cpp:26551
QCPSelectionDecorator::brush
QBrush brush() const
Definition: qcustomplot.h:3420
QCPLayer::addChild
void addChild(QCPLayerable *layerable, bool prepend)
Definition: qcustomplot.cpp:1224
QCPPlottableLegendItem
A legend item representing a plottable with an icon and the plottable name.
Definition: qcustomplot.h:5077
QCPScatterStyle::ssCrossSquare
@ ssCrossSquare
\enumimage{ssCrossSquare.png} a square with a cross inside
Definition: qcustomplot.h:2503
QCPSelectionDecoratorBracket::setTangentAverage
void setTangentAverage(int pointCount)
Definition: qcustomplot.cpp:17227
QCPAbstractPlottable::setKeyAxis
void setKeyAxis(QCPAxis *axis)
Definition: qcustomplot.cpp:11513
QCPPolarAxisRadial::getLabelFont
QFont getLabelFont() const
Definition: qcustomplot.cpp:32402
QCPColorGradient::mColorStops
QMap< double, QColor > mColorStops
Definition: qcustomplot.h:4794
QCustomPlot::updateLayerIndices
void updateLayerIndices() const
Definition: qcustomplot.cpp:16277
QCPScatterStyle::shape
ScatterShape shape() const
Definition: qcustomplot.h:2523
QCPAxisTickerPi::mPiTickStep
double mPiTickStep
Definition: qcustomplot.h:1980
QCustomPlot::axisRect
QCPAxisRect * axisRect(int index=0) const
Definition: qcustomplot.cpp:14905
QCPPolarLegendItem::QCPPolarLegendItem
QCPPolarLegendItem(QCPLegend *parent, QCPPolarGraph *graph)
Definition: qcustomplot.cpp:34329
QCPColorMapData::mAlpha
unsigned char * mAlpha
Definition: qcustomplot.h:6032
QCPRange::minRange
static const double minRange
Definition: qcustomplot.h:832
QCPPolarGrid::setRadialAxis
void setRadialAxis(QCPPolarAxisRadial *axis)
Definition: qcustomplot.cpp:34170
QCPItemPosition::PositionType
PositionType
Definition: qcustomplot.h:3616
QCPAxisTickerFixed::mScaleStrategy
ScaleStrategy mScaleStrategy
Definition: qcustomplot.h:1892
QCPLayoutElement::calculateAutoMargin
virtual int calculateAutoMargin(QCP::MarginSide side)
Definition: qcustomplot.cpp:3568
QCPItemPixmap::mPixmap
QPixmap mPixmap
Definition: qcustomplot.h:6792
QCPAxisPainterPrivate::drawTickLabel
virtual void drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const
Definition: qcustomplot.cpp:10302
QCPSelectionDecoratorBracket::setBracketWidth
void setBracketWidth(int width)
Definition: qcustomplot.cpp:17182
QCustomPlot::mViewport
QRect mViewport
Definition: qcustomplot.h:3933
QCPPaintBufferPixmap::draw
virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:688
QCPAxisRect::rangeZoomFactor
double rangeZoomFactor(Qt::Orientation orientation)
Definition: qcustomplot.cpp:18185
QCPAbstractPlottable::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:11947
QCPBars::mBarsGroup
QCPBarsGroup * mBarsGroup
Definition: qcustomplot.h:5840
QCustomPlot::QCPLegend
friend class QCPLegend
Definition: qcustomplot.h:4011
QCPItemPosition::mPositionTypeY
PositionType mPositionTypeY
Definition: qcustomplot.h:3660
QCPLabelPainterPrivate::LabelData::baseBounds
QRect baseBounds
Definition: qcustomplot.h:1645
QCPSelectionDecoratorBracket::~QCPSelectionDecoratorBracket
virtual ~QCPSelectionDecoratorBracket() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:17155
QCPPolarAxisAngular::setBackground
void setBackground(const QPixmap &pm)
Definition: qcustomplot.cpp:33087
QCPCurve::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:22837
QCPPolarGraph::addData
void addData(const QVector< double > &keys, const QVector< double > &values, bool alreadySorted=false)
Definition: qcustomplot.cpp:34669
QCPAxisTickerPi::fractionToString
QString fractionToString(int numerator, int denominator) const
Definition: qcustomplot.cpp:7580
QCPAxisPainterPrivate::upperEnding
QCPLineEnding upperEnding
Definition: qcustomplot.h:2407
QCPPolarAxisRadial::mSelectedLabelFont
QFont mSelectedLabelFont
Definition: qcustomplot.h:7143
QCPPainter::mIsAntialiasing
bool mIsAntialiasing
Definition: qcustomplot.h:525
QCPTextElement::setFont
void setFont(const QFont &font)
Definition: qcustomplot.cpp:19813
QCPGrid::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:7902
QCPItemLine::getRectClippedLine
QLineF getRectClippedLine(const QCPVector2D &start, const QCPVector2D &end, const QRect &rect) const
Definition: qcustomplot.cpp:29126
QCPPlottableInterface1D
Defines an abstract interface for one-dimensional plottables.
Definition: qcustomplot.h:4123
QCustomPlot::QCustomPlot
QCustomPlot(QWidget *parent=nullptr)
Definition: qcustomplot.cpp:13593
QCPItemAnchor::mChildrenY
QSet< QCPItemPosition * > mChildrenY
Definition: qcustomplot.h:3587
QCPPolarLegendItem::getIconBorderPen
QPen getIconBorderPen() const
Definition: qcustomplot.cpp:34377
QCPColorScaleAxisRectPrivate
Definition: qcustomplot.h:5319
QCP::ExportPen
ExportPen
Definition: qcustomplot.h:196
QCPLayerable::moveToLayer
bool moveToLayer(QCPLayer *layer, bool prepend)
Definition: qcustomplot.cpp:1567
QCPCurve::LineStyle
LineStyle
Definition: qcustomplot.h:5611
QCPItemTracer::brush
QBrush brush() const
Definition: qcustomplot.h:6850
QCPItemTracer::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30547
QCPPolarGraph::data
QSharedPointer< QCPGraphDataContainer > data() const
Definition: qcustomplot.h:7633
QCPPainter::antialiasing
bool antialiasing() const
Definition: qcustomplot.h:501
QCPLayoutElement::mOuterRect
QRect mOuterRect
Definition: qcustomplot.h:1282
QCPPolarGraph::drawScatterPlot
virtual void drawScatterPlot(QCPPainter *painter, const QVector< QPointF > &scatters, const QCPScatterStyle &style) const
Definition: qcustomplot.cpp:35102
QCPLayoutGrid::setColumnStretchFactors
void setColumnStretchFactors(const QList< double > &factors)
Definition: qcustomplot.cpp:4265
QCPAxis::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9663
QCPAxisPainterPrivate::subTickLengthIn
int subTickLengthIn
Definition: qcustomplot.h:2417
QCPPolarLegendItem::minimumOuterSizeHint
virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:34362
QCPLabelPainterPrivate::setAnchorReference
void setAnchorReference(const QPointF &pixelPoint)
Definition: qcustomplot.cpp:5514
QCPLineEnding::style
EndingStyle style() const
Definition: qcustomplot.h:1525
QCPPolarAxisAngular::getSubTickPen
QPen getSubTickPen() const
Definition: qcustomplot.cpp:33899
QCPErrorBars::dataPixelPosition
virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28205
QCPItemText::mColor
QColor mColor
Definition: qcustomplot.h:6657
QCP::ruDotsPerMeter
@ ruDotsPerMeter
Resolution is given in dots per meter (dpm)
Definition: qcustomplot.h:186
QCPItemTracer::setGraph
void setGraph(QCPGraph *graph)
Definition: qcustomplot.cpp:30498
QCPColorScale::dataRangeChanged
void dataRangeChanged(const QCPRange &newRange)
Definition: moc_qcustomplot.cpp:5420
QCPPolarAxisRadial::mTickPen
QPen mTickPen
Definition: qcustomplot.h:7159
QCP::isInvalidData
bool isInvalidData(double value)
Definition: qcustomplot.h:327
QCPAbstractPlottable::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const =0
QCPPolarAxisRadial::tickLabelMode
LabelMode tickLabelMode() const
Definition: qcustomplot.cpp:31130
QCustomPlot::plottable
QCPAbstractPlottable * plottable()
Definition: qcustomplot.cpp:14258
QCPAxisRect::mAADragBackup
QCP::AntialiasedElements mAADragBackup
Definition: qcustomplot.h:4981
QCPAxisPainterPrivate::subTickLengthOut
int subTickLengthOut
Definition: qcustomplot.h:2417
QCustomPlot::setSelectionTolerance
void setSelectionTolerance(int pixels)
Definition: qcustomplot.cpp:13897
QCPScatterStyle::mPen
QPen mPen
Definition: qcustomplot.h:2550
QCPPolarAxisRadial::mTickLengthOut
int mTickLengthOut
Definition: qcustomplot.h:7158
QCPAxis::coordToPixel
double coordToPixel(double value) const
Definition: qcustomplot.cpp:9299
QCPColorScale::mBarWidth
int mBarWidth
Definition: qcustomplot.h:5399
QCPAxis::calculateMargin
virtual int calculateMargin()
Definition: qcustomplot.cpp:9824
QCPItemPixmap::transformationMode
Qt::TransformationMode transformationMode() const
Definition: qcustomplot.h:6766
QCPLegend::mSelectableParts
SelectableParts mSelectableParts
Definition: qcustomplot.h:5197
QCPSelectionRect::moveSelection
virtual void moveSelection(QMouseEvent *event)
Definition: qcustomplot.cpp:2931
QCPDataSelection::operator-=
QCPDataSelection & operator-=(const QCPDataSelection &other)
Definition: qcustomplot.cpp:2470
QCPCurve::getOptimizedCornerPoints
QVector< QPointF > getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const
Definition: qcustomplot.cpp:23394
QCP::iNone
@ iNone
0x000 None of the interactions are possible
Definition: qcustomplot.h:272
QCPPolarAxisAngular::radius
double radius() const
Definition: qcustomplot.h:7389
QCustomPlot::draw
virtual void draw(QCPPainter *painter)
Definition: qcustomplot.cpp:15721
QCPAbstractPaintBuffer
The abstract base class for paint buffers, which define the rendering backend.
Definition: qcustomplot.h:539
QCPPolarGrid::mType
GridTypes mType
Definition: qcustomplot.h:7541
QCPItemPosition::mKey
double mKey
Definition: qcustomplot.h:3663
QCPAbstractItem::anchor
QCPItemAnchor * anchor(const QString &name) const
Definition: qcustomplot.cpp:13053
QCPGraph::setLineStyle
void setLineStyle(LineStyle ls)
Definition: qcustomplot.cpp:20925
QCPPolarAxisRadial::mDragging
bool mDragging
Definition: qcustomplot.h:7173
QCPAbstractPlottable::setSelectable
Q_SLOT void setSelectable(QCP::SelectionType selectable)
Definition: qcustomplot.cpp:11599
QCPPolarGraph::mLineStyle
LineStyle mLineStyle
Definition: qcustomplot.h:7683
QCPFinancial::setPenNegative
void setPenNegative(const QPen &pen)
Definition: qcustomplot.cpp:27216
QCPLegend::selectableParts
SelectableParts selectableParts() const
Definition: qcustomplot.h:5145
QCPGraph::mScatterStyle
QCPScatterStyle mScatterStyle
Definition: qcustomplot.h:5515
QCPAbstractItem::setClipToAxisRect
void setClipToAxisRect(bool clip)
Definition: qcustomplot.cpp:12961
QCPPolarAxisAngular::mSubTickVector
QVector< double > mSubTickVector
Definition: qcustomplot.h:7448
QCPItemBracket::right
QCPItemPosition *const right
Definition: qcustomplot.h:6944
QCPPolarAxisAngular::mRangeDrag
bool mRangeDrag
Definition: qcustomplot.h:7405
QCPAxis::padding
int padding() const
Definition: qcustomplot.h:2209
QCPPolarAxisRadial::setTicks
void setTicks(bool show)
Definition: qcustomplot.cpp:31443
QCPItemPixmap::setScaled
void setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio, Qt::TransformationMode transformationMode=Qt::SmoothTransformation)
Definition: qcustomplot.cpp:30162
QCPScatterStyle::spSize
@ spSize
0x04 The size property, see setSize
Definition: qcustomplot.h:2477
QCPLayoutGrid::setColumnStretchFactor
void setColumnStretchFactor(int column, double factor)
Definition: qcustomplot.cpp:4241
QCPItemLine::mPen
QPen mPen
Definition: qcustomplot.h:6461
QCPAbstractPlottable1D< QCPGraphData >::mDataContainer
QSharedPointer< QCPDataContainer< QCPGraphData > > mDataContainer
Definition: qcustomplot.h:4167
QCPSelectionDecorator::getFinalScatterStyle
QCPScatterStyle getFinalScatterStyle(const QCPScatterStyle &unselectedStyle) const
Definition: qcustomplot.cpp:11137
QCPPolarGraph::removeFromLegend
bool removeFromLegend(QCPLegend *legend) const
Definition: qcustomplot.cpp:34857
QCPScatterStyle::ssPixmap
@ ssPixmap
a custom pixmap specified by setPixmap, centered on the data point coordinates
Definition: qcustomplot.h:2508
QCPPolarAxisAngular::mTickLabelColor
QColor mTickLabelColor
Definition: qcustomplot.h:7423
QCPLayoutElement::mMargins
QMargins mMargins
Definition: qcustomplot.h:1283
QCPGrid::setZeroLinePen
void setZeroLinePen(const QPen &pen)
Definition: qcustomplot.cpp:7921
QCPLegend::mSelectedTextColor
QColor mSelectedTextColor
Definition: qcustomplot.h:5201
QCPLayout
The abstract base class for layouts.
Definition: qcustomplot.h:1306
QCPPolarGraph::mName
QString mName
Definition: qcustomplot.h:7685
QCPItemPosition::mParentAnchorY
QCPItemAnchor * mParentAnchorY
Definition: qcustomplot.h:3664
QCustomPlot::processRectSelection
virtual Q_SLOT void processRectSelection(QRect rect, QMouseEvent *event)
Definition: qcustomplot.cpp:16030
QCPFinancial::getPixelWidth
double getPixelWidth(double key, double keyPixel) const
Definition: qcustomplot.cpp:27645
QCPLayerable::mVisible
bool mVisible
Definition: qcustomplot.h:754
QCPPolarGrid::mAntialiasedSubGrid
bool mAntialiasedSubGrid
Definition: qcustomplot.h:7543
QCP::aeZeroLine
@ aeZeroLine
0x0200 Zero-lines, see QCPGrid::setZeroLinePen
Definition: qcustomplot.h:244
QCustomPlot::mReplotTimeAverage
double mReplotTimeAverage
Definition: qcustomplot.h:3967
QCPFinancialData::close
double close
Definition: qcustomplot.h:6136
QCPPolarGrid::setAntialiasedZeroLine
void setAntialiasedZeroLine(bool enabled)
Definition: qcustomplot.cpp:34196
QCPPolarAxisAngular::mNumberPrecision
int mNumberPrecision
Definition: qcustomplot.h:7424
QCPLabelPainterPrivate::SymbolDot
static const QChar SymbolDot
Definition: qcustomplot.h:1630
QCPPolarAxisRadial::setSelectedParts
Q_SLOT void setSelectedParts(const QCPPolarAxisRadial::SelectableParts &selectedParts)
Definition: qcustomplot.cpp:31286
QCustomPlot::legendRemoved
virtual void legendRemoved(QCPLegend *legend)
Definition: qcustomplot.cpp:16007
QCPAbstractPlottable::pen
QPen pen() const
Definition: qcustomplot.h:3481
QCPLayer::setMode
void setMode(LayerMode mode)
Definition: qcustomplot.cpp:1127
QCPLayoutGrid::simplify
virtual void simplify() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4703
QCPPolarAxisAngular::setTickLabelColor
void setTickLabelColor(const QColor &color)
Definition: qcustomplot.cpp:33408
QCPAxis::setTickLabelSide
void setTickLabelSide(LabelSide side)
Definition: qcustomplot.cpp:8669
QCPItemText::anchorPixelPosition
virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29805
QCPBars::setBaseValue
void setBaseValue(double baseValue)
Definition: qcustomplot.cpp:24521
QCPPolarGraph::name
QString name() const
Definition: qcustomplot.h:7621
QCPSelectionDecoratorBracket::drawBracket
virtual void drawBracket(QCPPainter *painter, int direction) const
Definition: qcustomplot.cpp:17247
QCPStatisticalBoxData::QCPStatisticalBoxData
QCPStatisticalBoxData()
Definition: qcustomplot.cpp:25193
QCPErrorBars::setWhiskerWidth
void setWhiskerWidth(double pixels)
Definition: qcustomplot.cpp:28073
QCPAbstractItem::QCPAbstractItem
QCPAbstractItem(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:12927
QCPLayoutElement::QCPLayoutElement
QCPLayoutElement(QCustomPlot *parentPlot=nullptr)
Definition: qcustomplot.cpp:3207
QCPItemPixmap::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:30175
QCPPolarAxisRadial::setSubTickLength
void setSubTickLength(int inside, int outside=0)
Definition: qcustomplot.cpp:31684
QCPAxis::opposite
static AxisType opposite(AxisType type)
Definition: qcustomplot.cpp:9469
QCPLayoutInset::insetPlacement
InsetPlacement insetPlacement(int index) const
Definition: qcustomplot.cpp:4901
QCPAxisPainterPrivate
Definition: qcustomplot.h:2390
QCPAbstractPlottable::mValueAxis
QPointer< QCPAxis > mValueAxis
Definition: qcustomplot.h:3532
QCPPolarAxisRadial::setLabel
void setLabel(const QString &str)
Definition: qcustomplot.cpp:31778
QCPColorGradient
Defines a color gradient for use with e.g. QCPColorMap.
Definition: qcustomplot.h:4715
QCPErrorBars::setDataPlottable
void setDataPlottable(QCPAbstractPlottable *plottable)
Definition: qcustomplot.cpp:28042
QCPPolarAxisRadial::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32146
QCPCurve::getRegion
int getRegion(double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const
Definition: qcustomplot.cpp:23234
QCPItemTracer::QCPItemTracer
QCPItemTracer(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:30407
QCPItemBracket::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30834
QCPLayoutInset::ipBorderAligned
@ ipBorderAligned
The element is aligned to one of the layout sides, see setInsetAlignment.
Definition: qcustomplot.h:1445
QCPTextElement::clicked
void clicked(QMouseEvent *event)
Definition: moc_qcustomplot.cpp:5038
QCPAxis::spNone
@ spNone
None of the selectable parts.
Definition: qcustomplot.h:2167
QCPPolarAxisRadial::mSelectedSubTickPen
QPen mSelectedSubTickPen
Definition: qcustomplot.h:7160
QCPColorGradient::NanHandling
NanHandling
Definition: qcustomplot.h:4734
QCPAxisTicker::mTickOrigin
double mTickOrigin
Definition: qcustomplot.h:1733
QCPAxisTickerPi::getSubTickCount
virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7505
QCPItemText::setTextAlignment
void setTextAlignment(Qt::Alignment alignment)
Definition: qcustomplot.cpp:29725
QCPSelectionRect::brush
QBrush brush() const
Definition: qcustomplot.h:1129
QCPGraph::lsNone
@ lsNone
Definition: qcustomplot.h:5473
QCPAxis::tickLabelRotation
double tickLabelRotation() const
Definition: qcustomplot.cpp:8278
QCPScatterStyle::ssStar
@ ssStar
\enumimage{ssStar.png} a star with eight arms, i.e. a combination of cross and plus
Definition: qcustomplot.h:2500
QCPLabelPainterPrivate::LabelData::baseFont
QFont baseFont
Definition: qcustomplot.h:1648
QCustomPlot::selectedAxes
QList< QCPAxis * > selectedAxes() const
Definition: qcustomplot.cpp:15021
QCPSelectionRect::mPen
QPen mPen
Definition: qcustomplot.h:1148
QCPColorMapData::setKeyRange
void setKeyRange(const QCPRange &keyRange)
Definition: qcustomplot.cpp:26010
QCPItemText::font
QFont font() const
Definition: qcustomplot.h:6617
QCPLabelPainterPrivate::setCacheSize
void setCacheSize(int labelCount)
Definition: qcustomplot.cpp:5563
QCPItemEllipse::aiTop
@ aiTop
Definition: qcustomplot.h:6726
QCPLayerable::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged)
Definition: qcustomplot.cpp:1710
QCPRange::expand
void expand(const QCPRange &otherRange)
Definition: qcustomplot.cpp:1959
QCPItemText::setColor
void setColor(const QColor &color)
Definition: qcustomplot.cpp:29617
QCPErrorBars::setSymbolGap
void setSymbolGap(double pixels)
Definition: qcustomplot.cpp:28083
QCPLineEnding::EndingStyle
EndingStyle
Definition: qcustomplot.h:1508
QCPFinancial::selectionHitBox
QRectF selectionHitBox(QCPFinancialDataContainer::const_iterator it) const
Definition: qcustomplot.cpp:27833
QCPPolarGraph::getLines
void getLines(QVector< QPointF > *lines, const QCPDataRange &dataRange) const
Definition: qcustomplot.cpp:35316
QCPPolarAxisRadial::setRangeReversed
void setRangeReversed(bool reversed)
Definition: qcustomplot.cpp:31398
QCPAxisRect::mRangeZoomFactorVert
double mRangeZoomFactorVert
Definition: qcustomplot.h:4977
QCPDataRange::size
int size() const
Definition: qcustomplot.h:926
QCPColorMapData::setCell
void setCell(int keyIndex, int valueIndex, double z)
Definition: qcustomplot.cpp:26068
QCPAxisPainterPrivate::getTickLabelDrawOffset
virtual QPointF getTickLabelDrawOffset(const TickLabelData &labelData) const
Definition: qcustomplot.cpp:10423
QCPItemCurve::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:29286
QCPAxisPainterPrivate::tickLabelPadding
int tickLabelPadding
Definition: qcustomplot.h:2412
QCPItemRect::bottomRight
QCPItemPosition *const bottomRight
Definition: qcustomplot.h:6558
QCPLayoutGrid::setWrap
void setWrap(int count)
Definition: qcustomplot.cpp:4372
QCPItemCurve::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29358
QCPItemStraightLine::pen
QPen pen() const
Definition: qcustomplot.h:6397
QCPErrorBars::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28388
QCPItemText::getTextDrawPoint
QPointF getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const
Definition: qcustomplot.cpp:29846
QCPAxisPainterPrivate::tickLabelRotation
double tickLabelRotation
Definition: qcustomplot.h:2413
QCPPolarAxisAngular::mSelectedLabelFont
QFont mSelectedLabelFont
Definition: qcustomplot.h:7416
QCustomPlot::plottableClick
void plottableClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3853
QCPColorMapData::isEmpty
bool isEmpty() const
Definition: qcustomplot.h:6020
QCPItemLine::head
QCPLineEnding head() const
Definition: qcustomplot.h:6444
QCPLayoutInset::setInsetRect
void setInsetRect(int index, const QRectF &rect)
Definition: qcustomplot.cpp:4986
QCPLayerable::setParentLayerable
void setParentLayerable(QCPLayerable *parentLayerable)
Definition: qcustomplot.cpp:1554
QCPItemLine::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:29044
QCPPolarGraph::pen
QPen pen() const
Definition: qcustomplot.h:7624
QCPAxisTicker::tssReadability
@ tssReadability
A nicely readable tick step is prioritized over matching the requested number of ticks (see setTickCo...
Definition: qcustomplot.h:1708
QCPLegend::spLegendBox
@ spLegendBox
0x001 The legend box (frame)
Definition: qcustomplot.h:5127
QCPAxisTicker::createTickVector
virtual QVector< double > createTickVector(double tickStep, const QCPRange &range)
Definition: qcustomplot.cpp:6338
QCPColorMapData::createAlpha
bool createAlpha(bool initializeOpaque=true)
Definition: qcustomplot.cpp:26258
QCPColorScale::mGradient
QCPColorGradient mGradient
Definition: qcustomplot.h:5398
QCustomPlot::selectedGraphs
QList< QCPGraph * > selectedGraphs() const
Definition: qcustomplot.cpp:14504
QCPAxis::numberFormat
QString numberFormat() const
Definition: qcustomplot.cpp:8290
QCPScatterStyle::ssTriangleInverted
@ ssTriangleInverted
\enumimage{ssTriangleInverted.png} an equilateral triangle, standing on corner
Definition: qcustomplot.h:2502
QCPAxis::moveRange
void moveRange(double diff)
Definition: qcustomplot.cpp:9111
QCPPolarAxisAngular::mBackgroundScaledMode
Qt::AspectRatioMode mBackgroundScaledMode
Definition: qcustomplot.h:7403
QCPSelectionDecorator::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:11079
QCPBarsGroup::stAbsolute
@ stAbsolute
Bar spacing is in absolute pixels.
Definition: qcustomplot.h:5694
QCPAxisTicker::TickStepStrategy
TickStepStrategy
Definition: qcustomplot.h:1706
QCPAbstractPlottable::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const =0
QCPGrid::mSubGridVisible
bool mSubGridVisible
Definition: qcustomplot.h:2066
QCPAxis::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9373
QCustomPlot::beforeReplot
void beforeReplot()
Definition: moc_qcustomplot.cpp:3915
QCPLabelPainterPrivate::mLabelCache
QCache< QString, CachedLabel > mLabelCache
Definition: qcustomplot.h:1667
QCPErrorBars::dataMainValue
virtual double dataMainValue(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28178
QCPAbstractItem::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:13112
QCPItemPosition::~QCPItemPosition
virtual ~QCPItemPosition() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:12223
QCPItemAnchor::pixelPosition
virtual QPointF pixelPosition() const
Definition: qcustomplot.cpp:12067
QCustomPlot::setSelectionRectMode
void setSelectionRectMode(QCP::SelectionRectMode mode)
Definition: qcustomplot.cpp:13978
QCPItemRect::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:29471
QCPAxisRect::rangeDragAxes
QList< QCPAxis * > rangeDragAxes(Qt::Orientation orientation)
Definition: qcustomplot.cpp:18133
QCustomPlot::mOpenGlMultisamples
int mOpenGlMultisamples
Definition: qcustomplot.h:3968
QCPPolarAxisAngular::mBackgroundScaled
bool mBackgroundScaled
Definition: qcustomplot.h:7402
QCPLegend::brush
QBrush brush() const
Definition: qcustomplot.h:5139
QCPPolarAxisAngular::mAADragBackup
QCP::AntialiasedElements mAADragBackup
Definition: qcustomplot.h:7453
QCPFinancial::drawCandlestickPlot
void drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, bool isSelected)
Definition: qcustomplot.cpp:27568
QCPLayout::simplify
virtual void simplify()
Definition: qcustomplot.cpp:3724
QCPTextElement::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19880
QCPColorMapData::alpha
unsigned char alpha(int keyIndex, int valueIndex)
Definition: qcustomplot.cpp:25903
QCPItemBracket::mLength
double mLength
Definition: qcustomplot.h:6951
QCPPolarGrid::gtAngular
@ gtAngular
Definition: qcustomplot.h:7504
QCPPolarAxisRadial::mSelectedParts
SelectableParts mSelectedParts
Definition: qcustomplot.h:7138
QCPColorMapData::setValueRange
void setValueRange(const QCPRange &valueRange)
Definition: qcustomplot.cpp:26025
QCPLabelPainterPrivate::mAnchorReferenceType
AnchorReferenceType mAnchorReferenceType
Definition: qcustomplot.h:1656
QCPPolarAxisRadial::mTicks
bool mTicks
Definition: qcustomplot.h:7156
QCPLayoutElement::sizeConstraintRect
SizeConstraintRect sizeConstraintRect() const
Definition: qcustomplot.h:1252
QCPSelectionDecorator::mPlottable
QCPAbstractPlottable * mPlottable
Definition: qcustomplot.h:3446
QCP::srmNone
@ srmNone
The selection rect is disabled, and all mouse events are forwarded to the underlying objects,...
Definition: qcustomplot.h:290
QCPLayerable::setLayer
Q_SLOT bool setLayer(QCPLayer *layer)
Definition: qcustomplot.cpp:1411
QCPFinancial::mChartStyle
ChartStyle mChartStyle
Definition: qcustomplot.h:6229
QCustomPlot
The central class of the library. This is the QWidget which displays the plot and interacts with the ...
Definition: qcustomplot.h:3753
QCPGraph::getLines
void getLines(QVector< QPointF > *lines, const QCPDataRange &dataRange) const
Definition: qcustomplot.cpp:21229
QCPItemText::padding
QMargins padding() const
Definition: qcustomplot.h:6623
QCPItemRect::mSelectedBrush
QBrush mSelectedBrush
Definition: qcustomplot.h:6571
QCPStatisticalBox::setOutlierStyle
void setOutlierStyle(const QCPScatterStyle &style)
Definition: qcustomplot.cpp:25421
QCustomPlot::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15607
QCPItemText::aiBottom
@ aiBottom
Definition: qcustomplot.h:6654
QCPAxis::mSelectedSubTickPen
QPen mSelectedSubTickPen
Definition: qcustomplot.h:2330
QCPAxisTickerDateTime::setTimeZone
void setTimeZone(const QTimeZone &zone)
Definition: qcustomplot.cpp:6598
QCPLineEnding::esSquare
@ esSquare
A filled square.
Definition: qcustomplot.h:1513
QCPTextElement::mSelectedTextColor
QColor mSelectedTextColor
Definition: qcustomplot.h:5289
QCPPolarAxisAngular::update
virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32957
QCPErrorBars::mDataContainer
QSharedPointer< QCPErrorBarsDataContainer > mDataContainer
Definition: qcustomplot.h:6354
QCPPolarGraph::getVisibleDataBounds
void getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin, QCPGraphDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const
Definition: qcustomplot.cpp:35270
QCustomPlot::removePlottable
bool removePlottable(QCPAbstractPlottable *plottable)
Definition: qcustomplot.cpp:14275
QCPPolarAxisRadial::setTickLength
void setTickLength(int inside, int outside=0)
Definition: qcustomplot.cpp:31624
QCPBarsData::QCPBarsData
QCPBarsData()
Definition: qcustomplot.cpp:24318
QCPPolarAxisRadial::mRangeReversed
bool mRangeReversed
Definition: qcustomplot.h:7163
QCPItemText::aiTopLeft
@ aiTopLeft
Definition: qcustomplot.h:6654
QCPAbstractItem::positions
QList< QCPItemPosition * > positions() const
Definition: qcustomplot.h:3705
QCPSelectionDecorator::mUsedScatterProperties
QCPScatterStyle::ScatterProperties mUsedScatterProperties
Definition: qcustomplot.h:3444
QCPLayerable::draw
virtual void draw(QCPPainter *painter)=0
QCPAbstractLegendItem::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18821
QCPItemAnchor::mParentItem
QCPAbstractItem * mParentItem
Definition: qcustomplot.h:3585
QCPLayoutElement::setMarginGroup
void setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group)
Definition: qcustomplot.cpp:3396
QCPAbstractLegendItem::mFont
QFont mFont
Definition: qcustomplot.h:5055
QCPPolarAxisRadial::setTickLabelPadding
void setTickLabelPadding(int padding)
Definition: qcustomplot.cpp:31470
QCPAbstractPlottable::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:11483
QCPLabelPainterPrivate::setColor
void setColor(const QColor &color)
Definition: qcustomplot.cpp:5533
QCPTextElement::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19886
QCPLegend::mIconTextPadding
int mIconTextPadding
Definition: qcustomplot.h:5196
QCPScatterStyle::ssTriangle
@ ssTriangle
\enumimage{ssTriangle.png} an equilateral triangle, standing on baseline
Definition: qcustomplot.h:2501
QCPItemLine::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29086
QCPAxis::spAxisLabel
@ spAxisLabel
The axis label.
Definition: qcustomplot.h:2170
QCP::iMultiSelect
@ iMultiSelect
0x004 The user can select multiple objects by holding the modifier set by QCustomPlot::setMultiSelect...
Definition: qcustomplot.h:275
QCPAxisPainterPrivate::getMaxTickLabelSize
virtual void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const
Definition: qcustomplot.cpp:10524
QCPStatisticalBox::QCPStatisticalBox
QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:25292
QCPAxisPainterPrivate::axisRect
QRect axisRect
Definition: qcustomplot.h:2421
QCPColorScale::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20483
QCPLayoutGrid::maximumOuterSizeHint
virtual QSize maximumOuterSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4765
QCPLayout::sizeConstraintsChanged
void sizeConstraintsChanged() const
Definition: qcustomplot.cpp:3794
QCPItemText::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29773
QCPAxisTickerDateTime::mDateStrategy
enum QCPAxisTickerDateTime::DateStrategy mDateStrategy
QCPDataRange::bounded
QCPDataRange bounded(const QCPDataRange &other) const
Definition: qcustomplot.cpp:2283
QCPAxisTickerDateTime::dateTimeToKey
static double dateTimeToKey(const QDateTime &dateTime)
Definition: qcustomplot.cpp:6800
QCPItemText::aiBottomLeft
@ aiBottomLeft
Definition: qcustomplot.h:6654
QCPLegend::setIconTextPadding
void setIconTextPadding(int padding)
Definition: qcustomplot.cpp:19183
QCPLabelPainterPrivate::cacheSize
int cacheSize() const
Definition: qcustomplot.cpp:5568
QCPColorScaleAxisRectPrivate::axisSelectableChanged
Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts)
Definition: qcustomplot.cpp:20680
QCPErrorBars::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28326
QCPPolarAxisRadial::tickLengthIn
int tickLengthIn() const
Definition: qcustomplot.cpp:31156
QCPSelectionDecorator::QCPSelectionDecorator
QCPSelectionDecorator()
Definition: qcustomplot.cpp:11056
QCP::sdNegative
@ sdNegative
The negative sign domain, i.e. numbers smaller than zero.
Definition: qcustomplot.h:207
QCPItemLine::QCPItemLine
QCPItemLine(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:29023
QCPGraph::getFillPolygon
const QPolygonF getFillPolygon(const QVector< QPointF > *lineData, QCPDataRange segment) const
Definition: qcustomplot.cpp:22177
QCPLabelPainterPrivate::LabelData::transform
QTransform transform
Definition: qcustomplot.h:1643
QCPItemPixmap::pen
QPen pen() const
Definition: qcustomplot.h:6767
QCPPolarAxisAngular::setTickLabelFont
void setTickLabelFont(const QFont &font)
Definition: qcustomplot.cpp:33398
QCPPolarAxisAngular::mDragging
bool mDragging
Definition: qcustomplot.h:7450
QCPAxisPainterPrivate::tickLengthOut
int tickLengthOut
Definition: qcustomplot.h:2417
QCPScatterStyle::customPath
QPainterPath customPath() const
Definition: qcustomplot.h:2527
QCPItemTracer::setGraphKey
void setGraphKey(double key)
Definition: qcustomplot.cpp:30525
QCPGraph::setAdaptiveSampling
void setAdaptiveSampling(bool enabled)
Definition: qcustomplot.cpp:21017
QCPRange::expanded
QCPRange expanded(const QCPRange &otherRange) const
Definition: qcustomplot.cpp:1998
QCPPolarAxisAngular::setSubTickLengthIn
void setSubTickLengthIn(int inside)
Definition: qcustomplot.cpp:33610
QCustomPlot::rpQueuedReplot
@ rpQueuedReplot
Queues the entire replot for the next event loop iteration. This way multiple redundant replots can b...
Definition: qcustomplot.h:3787
QCPItemEllipse::mPen
QPen mPen
Definition: qcustomplot.h:6729
QCPLabelPainterPrivate::rotation
double rotation() const
Definition: qcustomplot.h:1617
QCPCurve::lsNone
@ lsNone
No line is drawn between data points (e.g. only scatters)
Definition: qcustomplot.h:5611
QCPColorMap::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:26799
QCPPolarAxisRadial::setTickLabelFont
void setTickLabelFont(const QFont &font)
Definition: qcustomplot.cpp:31480
QCPPolarAxisRadial::mSelectedTickPen
QPen mSelectedTickPen
Definition: qcustomplot.h:7159
QCPColorScale
A color scale for use with color coding data such as QCPColorMap.
Definition: qcustomplot.h:5343
QCPPolarGrid::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:34255
QCPItemEllipse::setSelectedPen
void setSelectedPen(const QPen &pen)
Definition: qcustomplot.cpp:29968
QCPPolarAxisAngular::mBasePen
QPen mBasePen
Definition: qcustomplot.h:7412
QCPColorMap::setTightBoundary
void setTightBoundary(bool enabled)
Definition: qcustomplot.cpp:26532
QCP::msTop
@ msTop
0x04 top margin
Definition: qcustomplot.h:219
QCPAbstractItem::selectionChanged
void selectionChanged(bool selected)
Definition: moc_qcustomplot.cpp:3268
QCPGraph::mChannelFillGraph
QPointer< QCPGraph > mChannelFillGraph
Definition: qcustomplot.h:5517
QCPPolarGrid::setType
void setType(GridTypes type)
Definition: qcustomplot.cpp:34175
QCPItemPosition::setPixelPosition
void setPixelPosition(const QPointF &pixelPosition)
Definition: qcustomplot.cpp:12662
QCustomPlot::updateLayout
virtual void updateLayout()
Definition: qcustomplot.cpp:15752
QCPAxisRect::rangeDrag
Qt::Orientations rangeDrag() const
Definition: qcustomplot.h:4906
QCPAbstractPlottable::removeFromLegend
bool removeFromLegend(QCPLegend *legend) const
Definition: qcustomplot.cpp:11851
QCPAxisTicker::mTickCount
int mTickCount
Definition: qcustomplot.h:1732
QCPLayoutElement::upPreparation
@ upPreparation
Phase used for any type of preparation that needs to be done before margin calculation and layout.
Definition: qcustomplot.h:1221
QCPTextElement::selectionChanged
void selectionChanged(bool selected)
Definition: moc_qcustomplot.cpp:5024
QCPVector2D::isNull
bool isNull() const
Definition: qcustomplot.h:430
QCPLayoutElement::update
virtual void update(UpdatePhase phase)
Definition: qcustomplot.cpp:3436
QCPColorMapData
Holds the two-dimensional data of a QCPColorMap plottable.
Definition: qcustomplot.h:5985
QCustomPlot::mAntialiasedElements
QCP::AntialiasedElements mAntialiasedElements
Definition: qcustomplot.h:3941
QCPPolarAxisRadial::spAxisLabel
@ spAxisLabel
The axis label.
Definition: qcustomplot.h:6999
QCPAxis::range
const QCPRange range() const
Definition: qcustomplot.h:2183
QCPAxisPainterPrivate::subTickPositions
QVector< double > subTickPositions
Definition: qcustomplot.h:2426
QCPAxisPainterPrivate::tickPositions
QVector< double > tickPositions
Definition: qcustomplot.h:2427
QCPDataSelection::inverse
QCPDataSelection inverse(const QCPDataRange &outerRange) const
Definition: qcustomplot.cpp:2739
QCPAxis::SelectablePart
SelectablePart
Definition: qcustomplot.h:2167
QCPLayoutInset::mElements
QList< QCPLayoutElement * > mElements
Definition: qcustomplot.h:1477
QCPItemStraightLine::getRectClippedStraightLine
QLineF getRectClippedStraightLine(const QCPVector2D &base, const QCPVector2D &vec, const QRect &rect) const
Definition: qcustomplot.cpp:28909
QCustomPlot::replotTime
double replotTime(bool average=false) const
Definition: qcustomplot.cpp:15174
QCPAxis::lsOutside
@ lsOutside
Tick labels will be displayed outside the axis rect.
Definition: qcustomplot.h:2152
QCPStatisticalBox::getQuartileBox
QRectF getQuartileBox(QCPStatisticalBoxDataContainer::const_iterator it) const
Definition: qcustomplot.cpp:25715
QCPItemTracer::mGraphKey
double mGraphKey
Definition: qcustomplot.h:6884
QCPGraphData
Holds the data of one single data point for QCPGraph.
Definition: qcustomplot.h:5426
QCustomPlot::setNotAntialiasedElements
void setNotAntialiasedElements(const QCP::AntialiasedElements &notAntialiasedElements)
Definition: qcustomplot.cpp:13771
QCPGraph::drawFill
virtual void drawFill(QCPPainter *painter, QVector< QPointF > *lines) const
Definition: qcustomplot.cpp:21570
QCPAxisTicker::tssMeetTickCount
@ tssMeetTickCount
Less readable tick steps are allowed which in turn facilitates getting closer to the requested tick c...
Definition: qcustomplot.h:1709
QCPLayerable::setVisible
void setVisible(bool on)
Definition: qcustomplot.cpp:1397
QCPScatterStyle::QCPScatterStyle
QCPScatterStyle()
Definition: qcustomplot.cpp:10635
QCPAbstractPlottable::coordsToPixels
void coordsToPixels(double key, double value, double &x, double &y) const
Definition: qcustomplot.cpp:11625
QCPVector2D::normalize
void normalize()
Definition: qcustomplot.cpp:161
QCPAbstractItem::setClipAxisRect
void setClipAxisRect(QCPAxisRect *rect)
Definition: qcustomplot.cpp:12974
QCPCurve::setScatterSkip
void setScatterSkip(int skip)
Definition: qcustomplot.cpp:22714
QCPAxisRect::axis
QCPAxis * axis(QCPAxis::AxisType type, int index=0) const
Definition: qcustomplot.cpp:17604
QCPSelectionDecorator::registerWithPlottable
virtual bool registerWithPlottable(QCPAbstractPlottable *plottable)
Definition: qcustomplot.cpp:11185
QCPAbstractPlottable::applyScattersAntialiasingHint
void applyScattersAntialiasingHint(QCPPainter *painter) const
Definition: qcustomplot.cpp:11941
QCPItemAnchor::~QCPItemAnchor
virtual ~QCPItemAnchor()
Definition: qcustomplot.cpp:12046
QCustomPlot::QCPAxisRect
friend class QCPAxisRect
Definition: qcustomplot.h:4014
QCPDataSelection::operator==
bool operator==(const QCPDataSelection &other) const
Definition: qcustomplot.cpp:2434
QCPPolarAxisRadial::setSubTickLengthIn
void setSubTickLengthIn(int inside)
Definition: qcustomplot.cpp:31696
QCPAxis::items
QList< QCPAbstractItem * > items() const
Definition: qcustomplot.cpp:9429
QCPStatisticalBoxData
Holds the data of one single data point for QCPStatisticalBox.
Definition: qcustomplot.h:5868
QCPAxis::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9868
QCPColorGradient::color
QRgb color(double position, const QCPRange &range, bool logarithmic=false)
Definition: qcustomplot.cpp:16819
QCustomPlot::toPixmap
QPixmap toPixmap(int width=0, int height=0, double scale=1.0)
Definition: qcustomplot.cpp:16397
QCustomPlot::mMousePressPos
QPoint mMousePressPos
Definition: qcustomplot.h:3959
QCPAxisPainterPrivate::generateLabelParameterHash
virtual QByteArray generateLabelParameterHash() const
Definition: qcustomplot.cpp:10181
QCustomPlot::registerGraph
bool registerGraph(QCPGraph *graph)
Definition: qcustomplot.cpp:16225
QCPPolarAxisRadial::scaleType
ScaleType scaleType() const
Definition: qcustomplot.h:7019
QCPLayoutGrid::setRowSpacing
void setRowSpacing(int pixels)
Definition: qcustomplot.cpp:4350
QCP::aeNone
@ aeNone
0x0000 No elements
Definition: qcustomplot.h:247
QCPPolarAxisRadial::setBasePen
void setBasePen(const QPen &pen)
Definition: qcustomplot.cpp:31725
QCPBars::mBaseValue
double mBaseValue
Definition: qcustomplot.h:5841
QCustomPlot::mMultiSelectModifier
Qt::KeyboardModifier mMultiSelectModifier
Definition: qcustomplot.h:3952
QCPAxisRect::mDragStartHorzRange
QList< QCPRange > mDragStartHorzRange
Definition: qcustomplot.h:4980
QCPPolarGraph::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:34499
QCPFinancial::wtAxisRectRatio
@ wtAxisRectRatio
width is given by a fraction of the axis rect size
Definition: qcustomplot.h:6173
QCPPolarAxisRadial::mTickLengthIn
int mTickLengthIn
Definition: qcustomplot.h:7158
QCPAxis::mAxisType
AxisType mAxisType
Definition: qcustomplot.h:2302
QCPItemText::mBrush
QBrush mBrush
Definition: qcustomplot.h:6659
QCPAbstractPaintBuffer::mSize
QSize mSize
Definition: qcustomplot.h:563
QCPLabelPainterPrivate::createCachedLabel
CachedLabel * createCachedLabel(const LabelData &labelData) const
Definition: qcustomplot.cpp:5956
QCPPolarAxisAngular::mSubTickPen
QPen mSubTickPen
Definition: qcustomplot.h:7433
QCPStatisticalBox::mWhiskerAntialiased
bool mWhiskerAntialiased
Definition: qcustomplot.h:5958
QCPAxisTickerDateTime::setTickOrigin
void setTickOrigin(double origin)
Definition: qcustomplot.cpp:6614
QCPPolarAxisAngular::setLabel
void setLabel(const QString &str)
Definition: qcustomplot.cpp:33692
QCPGraph::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:21107
QCPAxis::atLeft
@ atLeft
0x01 Axis is vertical and on the left side of the axis rect
Definition: qcustomplot.h:2138
QCPPolarGraph::setAntialiasedFill
void setAntialiasedFill(bool enabled)
Definition: qcustomplot.cpp:34475
QCPPolarAxisAngular::setNumberPrecision
void setNumberPrecision(int precision)
Definition: qcustomplot.cpp:33521
QCPPolarAxisRadial::setRangeUpper
void setRangeUpper(double upper)
Definition: qcustomplot.cpp:31371
QCustomPlot::plottable
QCPAbstractPlottable * plottable(int index)
Definition: qcustomplot.cpp:14239
QCPColorMap::mLegendIcon
QPixmap mLegendIcon
Definition: qcustomplot.h:6101
QCPSelectionRect::isActive
bool isActive() const
Definition: qcustomplot.h:1130
QCPLayout::remove
bool remove(QCPLayoutElement *element)
Definition: qcustomplot.cpp:3760
QCPStatisticalBox::addData
void addData(const QVector< double > &keys, const QVector< double > &minimum, const QVector< double > &lowerQuartile, const QVector< double > &median, const QVector< double > &upperQuartile, const QVector< double > &maximum, bool alreadySorted=false)
Definition: qcustomplot.cpp:25438
QCPPolarGrid::mRadialSubGridPen
QPen mRadialSubGridPen
Definition: qcustomplot.h:7545
QCPErrorBars::~QCPErrorBars
virtual ~QCPErrorBars() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27970
QCPPolarAxisAngular::mAngle
double mAngle
Definition: qcustomplot.h:7410
QCPItemText::setPadding
void setPadding(const QMargins &padding)
Definition: qcustomplot.cpp:29743
QCPItemEllipse::aiBottomLeftRim
@ aiBottomLeftRim
Definition: qcustomplot.h:6726
QCPAbstractItem
The abstract base class for all items in a plot.
Definition: qcustomplot.h:3676
QCPAxisPainterPrivate::TickLabelData::suffixBounds
QRect suffixBounds
Definition: qcustomplot.h:2439
QCPDataRange
Describes a data range given by begin and end index.
Definition: qcustomplot.h:914
QCPScatterStyle::drawShape
void drawShape(QCPPainter *painter, const QPointF &pos) const
Definition: qcustomplot.cpp:10875
QCPAxisPainterPrivate::mLabelSelectionBox
QRect mLabelSelectionBox
Definition: qcustomplot.h:2445
QCPLabelPainterPrivate::artTangent
@ artTangent
Definition: qcustomplot.h:1574
QCPFinancialData::open
double open
Definition: qcustomplot.h:6136
QCPAxisTickerFixed::ssPowers
@ ssPowers
An integer power of the specified tick step is allowed.
Definition: qcustomplot.h:1875
QCPColorGradient::gpCold
@ gpCold
Continuous lightness from black over icey colors to white (suited for non-biased data representation)
Definition: qcustomplot.h:4748
QCPColorMap::dataRangeChanged
void dataRangeChanged(const QCPRange &newRange)
Definition: moc_qcustomplot.cpp:6442
QCPItemPosition::axisRect
QCPAxisRect * axisRect() const
Definition: qcustomplot.cpp:12246
QCPLayoutGrid::setRowStretchFactors
void setRowStretchFactors(const QList< double > &factors)
Definition: qcustomplot.cpp:4318
QCustomPlot::freeOpenGl
void freeOpenGl()
Definition: qcustomplot.cpp:15974
QCPPolarGraph::mValueAxis
QPointer< QCPPolarAxisRadial > mValueAxis
Definition: qcustomplot.h:7691
QCPBars::data
QSharedPointer< QCPBarsDataContainer > data() const
Definition: qcustomplot.h:5812
QCPAxisRect::items
QList< QCPAbstractItem * > items() const
Definition: qcustomplot.cpp:17936
QCPPaintBufferPixmap::clear
void clear(const QColor &color) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:697
QCPLayoutElement::marginGroup
QCPMarginGroup * marginGroup(QCP::MarginSide side) const
Definition: qcustomplot.h:1253
QCPPolarAxisRadial::mBasePen
QPen mBasePen
Definition: qcustomplot.h:7139
QCPPolarAxisAngular::setSelectedLabelFont
void setSelectedLabelFont(const QFont &font)
Definition: qcustomplot.cpp:33734
QCPPolarAxisRadial::setNumberPrecision
void setNumberPrecision(int precision)
Definition: qcustomplot.cpp:31607
QCPItemPixmap::scaled
bool scaled() const
Definition: qcustomplot.h:6764
QCP::iSelectOther
@ iSelectOther
0x080 All other objects are selectable (e.g. your own derived layerables, other layout elements,...
Definition: qcustomplot.h:280
QCPCurve::mayTraverse
bool mayTraverse(int prevRegion, int currentRegion) const
Definition: qcustomplot.cpp:23558
QCPLayoutGrid::elements
virtual QList< QCPLayoutElement * > elements(bool recursive) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4680
QCustomPlot::yAxis
QCPAxis * yAxis
Definition: qcustomplot.h:3907
QCPScatterStyle::spBrush
@ spBrush
0x02 The brush property, see setBrush
Definition: qcustomplot.h:2476
QCPStatisticalBox::getVisibleDataBounds
void getVisibleDataBounds(QCPStatisticalBoxDataContainer::const_iterator &begin, QCPStatisticalBoxDataContainer::const_iterator &end) const
Definition: qcustomplot.cpp:25695
QCPLayoutGrid::updateLayout
virtual void updateLayout() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4589
QCPScatterStyle::setCustomPath
void setCustomPath(const QPainterPath &customPath)
Definition: qcustomplot.cpp:10835
QCPAbstractPaintBuffer::setDevicePixelRatio
void setDevicePixelRatio(double ratio)
Definition: qcustomplot.cpp:638
QCPAbstractPlottable::clipRect
virtual QRect clipRect() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:11880
QCPAxis::tickLengthOut
int tickLengthOut() const
Definition: qcustomplot.cpp:8310
QCPColorMapData::clearAlpha
void clearAlpha()
Definition: qcustomplot.cpp:26155
QCPPolarAxisRadial::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32429
QCPItemPixmap::pixmap
QPixmap pixmap() const
Definition: qcustomplot.h:6763
QCPCurve::getTraverse
bool getTraverse(double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin, QPointF &crossA, QPointF &crossB) const
Definition: qcustomplot.cpp:23661
QCPErrorBars::etValueError
@ etValueError
The errors are for the value dimension (bars appear parallel to the value axis)
Definition: qcustomplot.h:6308
QCPAxis::atBottom
@ atBottom
0x08 Axis is horizontal and on the bottom side of the axis rect
Definition: qcustomplot.h:2141
QCPAxisTickerTime::tuMinutes
@ tuMinutes
Minutes (%m in setTimeFormat)
Definition: qcustomplot.h:1822
QCPLegend::spItems
@ spItems
0x002 Legend items individually (see selectedItems)
Definition: qcustomplot.h:5128
QCPAxisTickerFixed
Specialized axis ticker with a fixed tick step.
Definition: qcustomplot.h:1863
QCPPolarAxisRadial::setLabelColor
void setLabelColor(const QColor &color)
Definition: qcustomplot.cpp:31769
QCPTextElement::setText
void setText(const QString &text)
Definition: qcustomplot.cpp:19778
QCPRange::size
double size() const
Definition: qcustomplot.h:818
QCPPolarAxisRadial::labelPadding
int labelPadding() const
Definition: qcustomplot.cpp:31180
QCPAxisRect::insetLayout
QCPLayoutInset * insetLayout() const
Definition: qcustomplot.h:4939
QCPTextElement::mSelected
bool mSelected
Definition: qcustomplot.h:5291
QCPAbstractItem::createAnchor
QCPItemAnchor * createAnchor(const QString &name, int anchorId)
Definition: qcustomplot.cpp:13220
QCPAxisPainterPrivate::tickPen
QPen tickPen
Definition: qcustomplot.h:2418
QCPPolarAxisRadial::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:32296
QCPAxisTickerDateTime::keyToDateTime
static QDateTime keyToDateTime(double key)
Definition: qcustomplot.cpp:6780
QCPColorScale::label
QString label() const
Definition: qcustomplot.cpp:20127
QCPItemEllipse::setSelectedBrush
void setSelectedBrush(const QBrush &brush)
Definition: qcustomplot.cpp:29990
QCPItemText::~QCPItemText
virtual ~QCPItemText() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29610
QCPPolarAxisAngular::setTicks
void setTicks(bool show)
Definition: qcustomplot.cpp:33361
QCPItemLine::tail
QCPLineEnding tail() const
Definition: qcustomplot.h:6445
QCPPolarGraph::setScatterStyle
void setScatterStyle(const QCPScatterStyle &style)
Definition: qcustomplot.cpp:34664
QCPItemPixmap::aiBottomLeft
@ aiBottomLeft
Definition: qcustomplot.h:6789
QCPLabelPainterPrivate::LabelData::totalBounds
QRect totalBounds
Definition: qcustomplot.h:1646
QCPItemText::QCPItemText
QCPItemText(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:29584
QCPGraph::getOverlappingSegments
QVector< QPair< QCPDataRange, QCPDataRange > > getOverlappingSegments(QVector< QCPDataRange > thisSegments, const QVector< QPointF > *thisData, QVector< QCPDataRange > otherSegments, const QVector< QPointF > *otherData) const
Definition: qcustomplot.cpp:22022
QCustomPlot::saveRastered
bool saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
Definition: qcustomplot.cpp:16370
QCPGraph::setChannelFillGraph
void setChannelFillGraph(QCPGraph *targetGraph)
Definition: qcustomplot.cpp:20966
QCPAbstractItem::selectable
bool selectable() const
Definition: qcustomplot.h:3692
QCPLayoutElement::mSizeConstraintRect
SizeConstraintRect mSizeConstraintRect
Definition: qcustomplot.h:1281
QCPItemTracer::mStyle
TracerStyle mStyle
Definition: qcustomplot.h:6882
QCPPolarGraph::pointDistance
double pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const
Definition: qcustomplot.cpp:35154
QCPAxis::numberPrecision
int numberPrecision() const
Definition: qcustomplot.h:2194
QCPAbstractLegendItem::selectionCategory
virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19598
QCPAbstractPlottable::mSelectionDecorator
QCPSelectionDecorator * mSelectionDecorator
Definition: qcustomplot.h:3535
QCPGraph::lsStepLeft
@ lsStepLeft
line is drawn as steps where the step height is the value of the left data point
Definition: qcustomplot.h:5476
QCustomPlot::RefreshPriority
RefreshPriority
Definition: qcustomplot.h:3784
QCPAxisTickerDateTime::mDateTimeSpec
Qt::TimeSpec mDateTimeSpec
Definition: qcustomplot.h:1791
QCustomPlot::setSelectionRect
void setSelectionRect(QCPSelectionRect *selectionRect)
Definition: qcustomplot.cpp:14011
QCPPolarGraph::getScatters
void getScatters(QVector< QPointF > *scatters, const QCPDataRange &dataRange) const
Definition: qcustomplot.cpp:35338
QCustomPlot::setAntialiasedElements
void setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements)
Definition: qcustomplot.cpp:13725
QCPFinancialData::high
double high
Definition: qcustomplot.h:6136
QCPVector2D::QCPVector2D
QCPVector2D()
Definition: qcustomplot.cpp:118
QCPAxisPainterPrivate::TickLabelData::suffixPart
QString suffixPart
Definition: qcustomplot.h:2438
QCPLayerable::applyAntialiasingHint
void applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const
Definition: qcustomplot.cpp:1598
QCPColorGradient::colorize
void colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false)
Definition: qcustomplot.cpp:16690
QCPPolarGraph::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const
Definition: qcustomplot.cpp:34921
QCP::srmZoom
@ srmZoom
When dragging the mouse, a selection rect becomes active. Upon releasing, the axes that are currently...
Definition: qcustomplot.h:291
QCPSelectionDecorator::applyBrush
void applyBrush(QCPPainter *painter) const
Definition: qcustomplot.cpp:11124
QCustomPlot::setPlottingHints
void setPlottingHints(const QCP::PlottingHints &hints)
Definition: qcustomplot.cpp:13921
QCPSelectionRect::cancel
Q_SLOT void cancel()
Definition: qcustomplot.cpp:2903
QCPItemRect::aiTop
@ aiTop
Definition: qcustomplot.h:6567
QCPColorScale::mColorAxis
QPointer< QCPAxis > mColorAxis
Definition: qcustomplot.h:5403
QCPAxis::mTickLabelColor
QColor mTickLabelColor
Definition: qcustomplot.h:2320
QCustomPlot::limAbove
@ limAbove
Layer is inserted above other layer.
Definition: qcustomplot.h:3775
QCPPolarAxisAngular::spNone
@ spNone
None of the selectable parts.
Definition: qcustomplot.h:7232
QCPAxis::rescale
void rescale(bool onlyVisiblePlottables=false)
Definition: qcustomplot.cpp:9213
QCPLayoutInset::mInsetAlignment
QList< Qt::Alignment > mInsetAlignment
Definition: qcustomplot.h:1479
QCustomPlot::afterReplot
void afterReplot()
Definition: moc_qcustomplot.cpp:3927
QCPPolarAxisRadial::radiusToCoord
double radiusToCoord(double radius) const
Definition: qcustomplot.cpp:32050
QCPFinancial::mBrushPositive
QBrush mBrushPositive
Definition: qcustomplot.h:6233
QCPAbstractPlottable::pixelsToCoords
void pixelsToCoords(double x, double y, double &key, double &value) const
Definition: qcustomplot.cpp:11667
QCustomPlot::registerPlottable
bool registerPlottable(QCPAbstractPlottable *plottable)
Definition: qcustomplot.cpp:16194
QCPPolarGraph::selectionChanged
void selectionChanged(bool selected)
Definition: moc_qcustomplot.cpp:8881
QCPStatisticalBox::setWhiskerPen
void setWhiskerPen(const QPen &pen)
Definition: qcustomplot.cpp:25377
QCPAxisTickerPi::setFractionStyle
void setFractionStyle(FractionStyle style)
Definition: qcustomplot.cpp:7477
QCPAxisPainterPrivate::mAxisSelectionBox
QRect mAxisSelectionBox
Definition: qcustomplot.h:2445
QCPPolarAxisAngular::mAngleRad
double mAngleRad
Definition: qcustomplot.h:7410
QCustomPlot::mLayers
QList< QCPLayer * > mLayers
Definition: qcustomplot.h:3940
QCPScatterStyle::applyTo
void applyTo(QCPPainter *painter, const QPen &defaultPen) const
Definition: qcustomplot.cpp:10861
QCPGrid
Responsible for drawing the grid of a QCPAxis.
Definition: qcustomplot.h:2034
QCPPolarGraph::setPeriodic
void setPeriodic(bool enabled)
Definition: qcustomplot.cpp:34518
QCustomPlot::resizeEvent
virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:15488
QCPLayoutElement::layoutChanged
virtual void layoutChanged()
Definition: qcustomplot.cpp:3584
QCPItemEllipse::mSelectedBrush
QBrush mSelectedBrush
Definition: qcustomplot.h:6730
QCPItemPixmap::mScaled
bool mScaled
Definition: qcustomplot.h:6794
QCustomPlot::setOpenGl
void setOpenGl(bool enabled, int multisampling=16)
Definition: qcustomplot.cpp:14063
QCPItemPixmap::mPen
QPen mPen
Definition: qcustomplot.h:6798
QCPScatterStyle::mBrush
QBrush mBrush
Definition: qcustomplot.h:2551
QCPPolarAxisRadial::spNone
@ spNone
None of the selectable parts.
Definition: qcustomplot.h:6996
QCPPolarAxisRadial::mTickLabelFont
QFont mTickLabelFont
Definition: qcustomplot.h:7149
QCPAxis::mTicks
bool mTicks
Definition: qcustomplot.h:2326
QCPPolarAxisRadial::arAngularAxis
@ arAngularAxis
The axis tilt is measured in the angular coordinate system given by the parent angular axis.
Definition: qcustomplot.h:6981
QCPLayoutElement::SizeConstraintRect
SizeConstraintRect
Definition: qcustomplot.h:1235
QCPAbstractLegendItem::selectEvent
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18847
QCPScatterStyle::setSize
void setSize(double size)
Definition: qcustomplot.cpp:10773
QCPItemLine::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:29096
QCPItemPosition::key
double key() const
Definition: qcustomplot.h:3637
QCPColorScale::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20489
QCPLegend::mBorderPen
QPen mBorderPen
Definition: qcustomplot.h:5191
QCPItemCurve::setTail
void setTail(const QCPLineEnding &tail)
Definition: qcustomplot.cpp:29322
QCPItemPosition::parentAnchor
QCPItemAnchor * parentAnchor() const
Definition: qcustomplot.h:3634
QCPColorScaleAxisRectPrivate::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20590
QCPPolarAxisAngular::setTickLength
void setTickLength(int inside, int outside=0)
Definition: qcustomplot.cpp:33538
QCPFinancial::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27303
QCPMarginGroup::mChildren
QHash< QCP::MarginSide, QList< QCPLayoutElement * > > mChildren
Definition: qcustomplot.h:1187
QCPGraph::QCPGraph
QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis)
Definition: qcustomplot.cpp:20860
QCPLegend::iconBorderPen
QPen iconBorderPen() const
Definition: qcustomplot.h:5144
QCPPolarGrid::mRadialPen
QPen mRadialPen
Definition: qcustomplot.h:7545
QCPAbstractPlottable::mSelection
QCPDataSelection mSelection
Definition: qcustomplot.h:3534
QCPAxis::setSubTickPen
void setSubTickPen(const QPen &pen)
Definition: qcustomplot.cpp:8908
QCPItemTracer::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:30453
QCPPolarAxisAngular::setLabelFont
void setLabelFont(const QFont &font)
Definition: qcustomplot.cpp:33669
QCPAbstractPlottable::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const =0
QCPLabelPainterPrivate::asTopRight
@ asTopRight
Definition: qcustomplot.h:1586
QCPColorScale::colorMaps
QList< QCPColorMap * > colorMaps() const
Definition: qcustomplot.cpp:20369
QCPPolarAxisAngular::mTickLabels
bool mTickLabels
Definition: qcustomplot.h:7420
QCPItemPosition::parentAnchorX
QCPItemAnchor * parentAnchorX() const
Definition: qcustomplot.h:3635
QCPAxis::mSelectableParts
SelectableParts mSelectableParts
Definition: qcustomplot.h:2307
QCPAxis::setTickLabelColor
void setTickLabelColor(const QColor &color)
Definition: qcustomplot.cpp:8639
QCPLegend::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:19511
QCPItemCurve::startDir
QCPItemPosition *const startDir
Definition: qcustomplot.h:6507
QCPAbstractPlottable::selectableChanged
void selectableChanged(QCP::SelectionType selectable)
Definition: moc_qcustomplot.cpp:2964
QCPItemEllipse::aiBottomRightRim
@ aiBottomRightRim
Definition: qcustomplot.h:6726
QCPPolarAxisRadial::mLabelColor
QColor mLabelColor
Definition: qcustomplot.h:7144
QCPLayerable::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const =0
QCP::stNone
@ stNone
The plottable is not selectable.
Definition: qcustomplot.h:314
QCPGraph::dataToStepRightLines
QVector< QPointF > dataToStepRightLines(const QVector< QCPGraphData > &data) const
Definition: qcustomplot.cpp:21411
QCPVector2D::angle
double angle() const
Definition: qcustomplot.h:426
QCPItemEllipse::aiRight
@ aiRight
Definition: qcustomplot.h:6726
QCPDataSelection::QCPDataSelection
QCPDataSelection()
Definition: qcustomplot.cpp:2415
QCPPolarAxisAngular::setNumberFormat
void setNumberFormat(const QString &formatCode)
Definition: qcustomplot.cpp:33466
QCPPlottableLegendItem::minimumOuterSizeHint
virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18983
QCPAbstractPaintBuffer::QCPAbstractPaintBuffer
QCPAbstractPaintBuffer(const QSize &size, double devicePixelRatio)
Definition: qcustomplot.cpp:581
QCPPolarGraph::getOptimizedScatterData
void getOptimizedScatterData(QVector< QCPGraphData > *scatterData, QCPGraphDataContainer::const_iterator begin, QCPGraphDataContainer::const_iterator end) const
Definition: qcustomplot.cpp:35453
QCPPolarAxisRadial::setTickPen
void setTickPen(const QPen &pen)
Definition: qcustomplot.cpp:31735
QCPPolarGraph::~QCPPolarGraph
virtual ~QCPPolarGraph()
Definition: qcustomplot.cpp:34449
QCPDataContainer
The generic data container for one-dimensional plottables.
Definition: qcustomplot.h:2578
QCPColorMap::setDataRange
Q_SLOT void setDataRange(const QCPRange &dataRange)
Definition: qcustomplot.cpp:26457
QCPItemEllipse::aiTopRightRim
@ aiTopRightRim
Definition: qcustomplot.h:6726
QCPAxis::setSubTickLengthIn
void setSubTickLengthIn(int inside)
Definition: qcustomplot.cpp:8859
QCPFinancial::setData
void setData(QSharedPointer< QCPFinancialDataContainer > data)
Definition: qcustomplot.cpp:27098
QCustomPlot::setBackground
void setBackground(const QPixmap &pm)
Definition: qcustomplot.cpp:14166
QCPGraph::drawScatterPlot
virtual void drawScatterPlot(QCPPainter *painter, const QVector< QPointF > &scatters, const QCPScatterStyle &style) const
Definition: qcustomplot.cpp:21604
QCPAxis::setLowerEnding
void setLowerEnding(const QCPLineEnding &ending)
Definition: qcustomplot.cpp:9084
QCPLayerable::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
Definition: qcustomplot.cpp:1758
QCPPolarAxisAngular::mSelectedSubTickPen
QPen mSelectedSubTickPen
Definition: qcustomplot.h:7433
QCPItemBracket::~QCPItemBracket
virtual ~QCPItemBracket() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30782
QCPColorMapData::cellToCoord
void cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const
Definition: qcustomplot.cpp:26237
QCustomPlot::plottableCount
int plottableCount() const
Definition: qcustomplot.cpp:14330
QCPDataRange::contains
bool contains(const QCPDataRange &other) const
Definition: qcustomplot.cpp:2339
QCustomPlot::mSelectionRect
QCPSelectionRect * mSelectionRect
Definition: qcustomplot.h:3954
QCPAxis::mRange
QCPRange mRange
Definition: qcustomplot.h:2332
QCPFinancial::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27338
QCPLayout::QCPLayout
QCPLayout()
Definition: qcustomplot.cpp:3666
QCP::getMarginValue
int getMarginValue(const QMargins &margins, QCP::MarginSide side)
Definition: qcustomplot.h:368
QCPPolarAxisAngular::setSelectedParts
Q_SLOT void setSelectedParts(const QCPPolarAxisAngular::SelectableParts &selectedParts)
Definition: qcustomplot.cpp:33226
QCPStatisticalBox::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:25558
QCPAxis::mTickLabelFont
QFont mTickLabelFont
Definition: qcustomplot.h:2319
QCPLegend::getBrush
QBrush getBrush() const
Definition: qcustomplot.cpp:19531
QCPColorMap::colorScale
QCPColorScale * colorScale() const
Definition: qcustomplot.h:6064
QCustomPlot::setInteractions
void setInteractions(const QCP::Interactions &interactions)
Definition: qcustomplot.cpp:13864
QCP::aeLegendItems
@ aeLegendItems
0x0010 Legend items
Definition: qcustomplot.h:239
QCPLegend::hasItemWithPlottable
bool hasItemWithPlottable(const QCPAbstractPlottable *plottable) const
Definition: qcustomplot.cpp:19398
QCPItemPosition::setType
void setType(PositionType type)
Definition: qcustomplot.cpp:12276
QCP::iSelectPlottables
@ iSelectPlottables
0x008 Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable)
Definition: qcustomplot.h:276
QCPLayout::getSectionSizes
QVector< int > getSectionSizes(QVector< int > maxSizes, QVector< int > minSizes, QVector< double > stretchFactors, int totalSize) const
Definition: qcustomplot.cpp:3896
QCPLineEnding::esSpikeArrow
@ esSpikeArrow
A filled arrow head with an indented back.
Definition: qcustomplot.h:1510
QCustomPlot::plottableAt
PlottableType * plottableAt(const QPointF &pos, bool onlySelectable=false, int *dataIndex=nullptr) const
Definition: qcustomplot.h:4044
QCPItemPosition::setTypeY
void setTypeY(PositionType type)
Definition: qcustomplot.cpp:12319
QCPPolarGraph::mKeyAxis
QPointer< QCPPolarAxisAngular > mKeyAxis
Definition: qcustomplot.h:7690
QCPPolarAxisRadial::numberFormat
QString numberFormat() const
Definition: qcustomplot.cpp:31142
QCPPolarGraph::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
Definition: qcustomplot.cpp:34893
QCPItemText::color
QColor color() const
Definition: qcustomplot.h:6611
QCPPolarAxisRadial::mCenter
QPointF mCenter
Definition: qcustomplot.h:7167
QCPColorMap
A plottable representing a two-dimensional color map in a plot.
Definition: qcustomplot.h:6042
QCPItemAnchor::removeChildY
void removeChildY(QCPItemPosition *pos)
Definition: qcustomplot.cpp:12136
QCPAxis::setScaleType
Q_SLOT void setScaleType(QCPAxis::ScaleType type)
Definition: qcustomplot.cpp:8365
QCPAxis::selectableChanged
void selectableChanged(const QCPAxis::SelectableParts &parts)
Definition: moc_qcustomplot.cpp:2500
QCPColorGradient::ciHSV
@ ciHSV
Color channels hue, saturation and value are linearly interpolated (The hue is interpolated over the ...
Definition: qcustomplot.h:4725
QCPSelectionRect::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:2883
QCP::stMultipleDataRanges
@ stMultipleDataRanges
Any combination of data points/ranges can be selected.
Definition: qcustomplot.h:318
QCPAxis::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9592
QCPAxis::setScaleRatio
void setScaleRatio(const QCPAxis *otherAxis, double ratio=1.0)
Definition: qcustomplot.cpp:9189
QCPItemText::brush
QBrush brush() const
Definition: qcustomplot.h:6615
QCPLayer::lmLogical
@ lmLogical
Layer is used only for rendering order, and shares paint buffer with all other adjacent logical layer...
Definition: qcustomplot.h:667
QCPGrid::mParentAxis
QCPAxis * mParentAxis
Definition: qcustomplot.h:2071
QCPLineEnding::esFlatArrow
@ esFlatArrow
A filled arrow head with a straight/flat back (a triangle)
Definition: qcustomplot.h:1509
QCPFinancial::setBrushPositive
void setBrushPositive(const QBrush &brush)
Definition: qcustomplot.cpp:27174
QCPPolarGrid::QCPPolarGrid
QCPPolarGrid(QCPPolarAxisAngular *parentAxis)
Definition: qcustomplot.cpp:34147
QCPPolarAxisRadial::coordToPixel
QPointF coordToPixel(double angleCoord, double radiusCoord) const
Definition: qcustomplot.cpp:32019
QCPLayoutElement::mMinimumMargins
QMargins mMinimumMargins
Definition: qcustomplot.h:1283
QCPLayoutInset::setInsetAlignment
void setInsetAlignment(int index, Qt::Alignment alignment)
Definition: qcustomplot.cpp:4967
QCPAbstractPlottable1D< QCPGraphData >::drawPolyline
void drawPolyline(QCPPainter *painter, const QVector< QPointF > &lineData) const
Definition: qcustomplot.h:4651
QCPSelectionDecoratorBracket::mBracketWidth
int mBracketWidth
Definition: qcustomplot.h:4868
QCPAxisTicker::mTickStepStrategy
TickStepStrategy mTickStepStrategy
Definition: qcustomplot.h:1731
QCPSelectionDecoratorBracket::setTangentToData
void setTangentToData(bool enabled)
Definition: qcustomplot.cpp:17214
QCPItemTracer::graph
QCPGraph * graph() const
Definition: qcustomplot.h:6854
QCPItemRect::pen
QPen pen() const
Definition: qcustomplot.h:6543
QCPPolarAxisRadial::mSubTickPen
QPen mSubTickPen
Definition: qcustomplot.h:7160
QCPGrid::applyDefaultAntialiasingHint
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7939
QCPAxisPainterPrivate::tickLabels
QVector< QString > tickLabels
Definition: qcustomplot.h:2428
QCPPolarAxisRadial::setSelectedTickPen
void setSelectedTickPen(const QPen &pen)
Definition: qcustomplot.cpp:31864
QCPColorMapData::setAlpha
void setAlpha(int keyIndex, int valueIndex, unsigned char alpha)
Definition: qcustomplot.cpp:26097
QCPCurve::~QCPCurve
virtual ~QCPCurve() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:22632
QCPColorGradient::levelCount
int levelCount() const
Definition: qcustomplot.h:4767
QCustomPlot::clearPlottables
int clearPlottables()
Definition: qcustomplot.cpp:14317
QCPAxisTickerPi::mPiSymbol
QString mPiSymbol
Definition: qcustomplot.h:1974
QCP::msNone
@ msNone
0x00 no margin
Definition: qcustomplot.h:222
QCPColorMap::drawLegendIcon
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:26868
QCPVector2D::operator-=
QCPVector2D & operator-=(const QCPVector2D &vector)
Definition: qcustomplot.cpp:265
QCPPolarAxisAngular::exactClipRegion
QRegion exactClipRegion() const
Definition: qcustomplot.cpp:32764
QCPDataSelection::isEmpty
bool isEmpty() const
Definition: qcustomplot.h:982
QCPPolarAxisAngular::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:33955
QCPAbstractLegendItem::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18861
QCPLayoutElement::setAutoMargins
void setAutoMargins(QCP::MarginSides sides)
Definition: qcustomplot.cpp:3296
QCPItemLine::start
QCPItemPosition *const start
Definition: qcustomplot.h:6456
QCPLayout::releaseElement
void releaseElement(QCPLayoutElement *el)
Definition: qcustomplot.cpp:3855
QCPLineEnding::esLineArrow
@ esLineArrow
A non-filled arrow head with open back.
Definition: qcustomplot.h:1511
QCPAxis::getPartAt
SelectablePart getPartAt(const QPointF &pos) const
Definition: qcustomplot.cpp:9357
QCPColorMapData::mKeySize
int mKeySize
Definition: qcustomplot.h:6026
QCPColorMapData::mKeyRange
QCPRange mKeyRange
Definition: qcustomplot.h:6027
QCPAxisPainterPrivate::TickLabelData::baseFont
QFont baseFont
Definition: qcustomplot.h:2440
QCPPolarAxisRadial::setLabelFont
void setLabelFont(const QFont &font)
Definition: qcustomplot.cpp:31755
QCPPolarAxisRadial::mTickLabels
bool mTickLabels
Definition: qcustomplot.h:7147
QCPAxisRect::mDragging
bool mDragging
Definition: qcustomplot.h:4982
QCPColorMap::mMapImageInvalidated
bool mMapImageInvalidated
Definition: qcustomplot.h:6102
QCPAxisRect::mRangeZoom
Qt::Orientations mRangeZoom
Definition: qcustomplot.h:4974
QCPFinancialData
Holds the data of one single data point for QCPFinancial.
Definition: qcustomplot.h:6121
QCPAxisTickerPi::unicodeSuperscript
QString unicodeSuperscript(int number) const
Definition: qcustomplot.cpp:7646
QCPPolarAxisAngular::mSelectedBasePen
QPen mSelectedBasePen
Definition: qcustomplot.h:7412
QCPPolarAxisAngular::mLabelColor
QColor mLabelColor
Definition: qcustomplot.h:7417
QCPAxis::getSubTickPen
QPen getSubTickPen() const
Definition: qcustomplot.cpp:9765
QCPGraph::lsStepCenter
@ lsStepCenter
line is drawn as steps where the step is in between two data points
Definition: qcustomplot.h:5478
QCPAxisPainterPrivate::tickLengthIn
int tickLengthIn
Definition: qcustomplot.h:2417
QCPPolarAxisAngular::mNumberMultiplyCross
bool mNumberMultiplyCross
Definition: qcustomplot.h:7427
QCPLabelPainterPrivate::applyAnchorTransform
void applyAnchorTransform(LabelData &labelData) const
Definition: qcustomplot.cpp:5906
QCPAxisRect::setRangeZoomFactor
void setRangeZoomFactor(double horizontalFactor, double verticalFactor)
Definition: qcustomplot.cpp:18384
QCPLayoutElement::UpdatePhase
UpdatePhase
Definition: qcustomplot.h:1221
QCPGrid::mPen
QPen mPen
Definition: qcustomplot.h:2068
QCPAbstractPlottable1D< QCPGraphData >::getDataSegments
void getDataSegments(QList< QCPDataRange > &selectedSegments, QList< QCPDataRange > &unselectedSegments) const
Definition: qcustomplot.h:4621
QCPLayoutGrid::element
QCPLayoutElement * element(int row, int column) const
Definition: qcustomplot.cpp:4127
QCPItemText::positionAlignment
Qt::Alignment positionAlignment() const
Definition: qcustomplot.h:6620
QCPLabelPainterPrivate::LabelData::side
AnchorSide side
Definition: qcustomplot.h:1641
QCPAxisPainterPrivate::TickLabelData::basePart
QString basePart
Definition: qcustomplot.h:2438
QCPPolarAxisRadial::pixelToCoord
void pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const
Definition: qcustomplot.cpp:32009
QCPLayoutGrid::mRowStretchFactors
QList< double > mRowStretchFactors
Definition: qcustomplot.h:1422
QCPStatisticalBox::getWhiskerBarLines
QVector< QLineF > getWhiskerBarLines(QCPStatisticalBoxDataContainer::const_iterator it) const
Definition: qcustomplot.cpp:25746
QCPColorMap::mColorScale
QPointer< QCPColorScale > mColorScale
Definition: qcustomplot.h:6097
QCPItemAnchor
An anchor of an item to which positions can be attached to.
Definition: qcustomplot.h:3568
QCPItemTracer::tsSquare
@ tsSquare
A square.
Definition: qcustomplot.h:6840
QCPPaintBufferPixmap::QCPPaintBufferPixmap
QCPPaintBufferPixmap(const QSize &size, double devicePixelRatio)
Definition: qcustomplot.cpp:667
QCPLineEnding::esBar
@ esBar
A bar perpendicular to the line.
Definition: qcustomplot.h:1515
QCPAbstractPlottable::interface1D
virtual QCPPlottableInterface1D * interface1D()
Definition: qcustomplot.h:3504
QCPLayer::mMode
LayerMode mMode
Definition: qcustomplot.h:697
QCPErrorBars::dataCount
virtual int dataCount() const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28152
QCPPolarAxisRadial::setTickLabelRotation
void setTickLabelRotation(double degrees)
Definition: qcustomplot.cpp:31508
QCPScatterStyle::pixmap
QPixmap pixmap() const
Definition: qcustomplot.h:2526
QCPLayoutElement::upLayout
@ upLayout
Final phase in which the layout system places the rects of the elements.
Definition: qcustomplot.h:1223
QCPPolarAxisAngular::setTickLabelPadding
void setTickLabelPadding(int padding)
Definition: qcustomplot.cpp:33388
QCPPolarAxisRadial::mAngularAxis
QCPPolarAxisAngular * mAngularAxis
Definition: qcustomplot.h:7135
QCPColorScale::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20500
QCPBars
A plottable representing a bar chart in a plot.
Definition: qcustomplot.h:5776
QCPAxis::setTickLabelPadding
void setTickLabelPadding(int padding)
Definition: qcustomplot.cpp:8611
QCPPolarAxisRadial::mAngleReference
AngleReference mAngleReference
Definition: qcustomplot.h:7137
QCPLabelPainterPrivate::anchorMode
AnchorMode anchorMode() const
Definition: qcustomplot.h:1610
QCPDataRange::adjusted
QCPDataRange adjusted(int changeBegin, int changeEnd) const
Definition: qcustomplot.h:939
QCustomPlot::plottableDoubleClick
void plottableDoubleClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3860
QCPColorMapData::recalculateDataBounds
void recalculateDataBounds()
Definition: qcustomplot.cpp:26123
QCPColorGradient::nhLowestColor
@ nhLowestColor
NaN data points appear as the lowest color defined in this QCPColorGradient.
Definition: qcustomplot.h:4735
QCustomPlot::currentLayer
QCPLayer * currentLayer() const
Definition: qcustomplot.cpp:14691
QCPLayoutInset::elementAt
virtual QCPLayoutElement * elementAt(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:5039
QCPPolarAxisAngular::getLabelColor
QColor getLabelColor() const
Definition: qcustomplot.cpp:33939
QCPPolarAxisAngular::mDragAngularStart
QCPRange mDragAngularStart
Definition: qcustomplot.h:7451
QCPPolarGraph::applyDefaultAntialiasingHint
void applyDefaultAntialiasingHint(QCPPainter *painter) const
Definition: qcustomplot.cpp:35008
QCPLineEnding::length
double length() const
Definition: qcustomplot.h:1527
QCustomPlot::saveJpg
bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
Definition: qcustomplot.cpp:15389
QCPLayoutInset::take
virtual bool take(QCPLayoutElement *element) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:5066
QCustomPlot::addGraph
QCPGraph * addGraph(QCPAxis *keyAxis=nullptr, QCPAxis *valueAxis=nullptr)
Definition: qcustomplot.cpp:14423
QCPPolarAxisRadial::mRange
QCPRange mRange
Definition: qcustomplot.h:7162
QCPAxisPainterPrivate::labelColor
QColor labelColor
Definition: qcustomplot.h:2410
QCPAbstractItem::setSelected
Q_SLOT void setSelected(bool selected)
Definition: qcustomplot.cpp:13013
QCPLayer::mChildren
QList< QCPLayerable * > mChildren
Definition: qcustomplot.h:695
QCPItemRect::QCPItemRect
QCPItemRect(QCustomPlot *parentPlot)
Definition: qcustomplot.cpp:29421
QCPAxisRect::right
int right() const
Definition: qcustomplot.h:4950
QCPItemPixmap::aiTopRight
@ aiTopRight
Definition: qcustomplot.h:6789
QCPBarsGroup::~QCPBarsGroup
virtual ~QCPBarsGroup()
Definition: qcustomplot.cpp:24001
QCPSelectionDecoratorBracket::QCPSelectionDecoratorBracket
QCPSelectionDecoratorBracket()
Definition: qcustomplot.cpp:17143
QCPAxisPainterPrivate::tickLabelColor
QColor tickLabelColor
Definition: qcustomplot.h:2420
QCPErrorBars::addData
void addData(const QVector< double > &error)
Definition: qcustomplot.cpp:28097
QCPItemText::mRotation
double mRotation
Definition: qcustomplot.h:6664
QCPTextElement::selected
bool selected() const
Definition: qcustomplot.h:5258
QCPItemRect::aiBottomLeft
@ aiBottomLeft
Definition: qcustomplot.h:6567
QCPColorMap::data
QCPColorMapData * data() const
Definition: qcustomplot.h:6058
QCP::stDataRange
@ stDataRange
Multiple contiguous data points (a data range) can be selected.
Definition: qcustomplot.h:317
QCPPolarAxisAngular::scaleRange
void scaleRange(double factor)
Definition: qcustomplot.cpp:32794
QCustomPlot::bufferDevicePixelRatio
double bufferDevicePixelRatio() const
Definition: qcustomplot.h:3796
QCPLineEnding::setInverted
void setInverted(bool inverted)
Definition: qcustomplot.cpp:5250
QCPRange::upper
double upper
Definition: qcustomplot.h:799
QCPAxisPainterPrivate::reversedEndings
bool reversedEndings
Definition: qcustomplot.h:2424
QCPItemPosition::mAxisRect
QPointer< QCPAxisRect > mAxisRect
Definition: qcustomplot.h:3662
QCPColorMap::mDataScaleType
QCPAxis::ScaleType mDataScaleType
Definition: qcustomplot.h:6092
QCPLabelPainterPrivate::asTop
@ asTop
Definition: qcustomplot.h:1583
QCPLayer::name
QString name() const
Definition: qcustomplot.h:677
QCPAxis::ScaleType
ScaleType
Definition: qcustomplot.h:2159
QCustomPlot::mMouseSignalLayerableDetails
QVariant mMouseSignalLayerableDetails
Definition: qcustomplot.h:3964
QCPMarginGroup
A margin group allows synchronization of margin sides if working with multiple layout elements.
Definition: qcustomplot.h:1172
QCPLineEnding::inverted
bool inverted() const
Definition: qcustomplot.h:1528
QCPLabelPainterPrivate::multiplicationSymbol
QChar multiplicationSymbol() const
Definition: qcustomplot.h:1619
QCPColorMapData::setKeySize
void setKeySize(int keySize)
Definition: qcustomplot.cpp:25964
QCPColorMap::setDataScaleType
Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType)
Definition: qcustomplot.cpp:26476
QCPGraph::mAdaptiveSampling
bool mAdaptiveSampling
Definition: qcustomplot.h:5518
QCPLayoutInset
A layout that places child elements aligned to the border or arbitrarily positioned.
Definition: qcustomplot.h:1437
QCPAxisTickerFixed::getTickStep
virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7157
QCPLayoutGrid::takeAt
virtual QCPLayoutElement * takeAt(int index) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:4644
QCPAbstractPaintBuffer::size
QSize size() const
Definition: qcustomplot.h:546
QCPPainter::pmVectorized
@ pmVectorized
0x01 Mode for vectorized painting (e.g. PDF export). For example, this prevents some antialiasing fix...
Definition: qcustomplot.h:489
QCPScatterStyle
Represents the visual appearance of scatter points.
Definition: qcustomplot.h:2462
QCPLineEnding::setWidth
void setWidth(double width)
Definition: qcustomplot.cpp:5226
QCPLabelPainterPrivate::amSkewedRotated
@ amSkewedRotated
Definition: qcustomplot.h:1566
QCPPolarAxisRadial::mLabel
QString mLabel
Definition: qcustomplot.h:7142
QCPBars::barBelow
QCPBars * barBelow() const
Definition: qcustomplot.h:5810
QCPAbstractItem::clipAxisRect
QCPAxisRect * clipAxisRect() const
Definition: qcustomplot.cpp:12950
QCPPolarGraph::getKeyRange
virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const
Definition: qcustomplot.cpp:34915
QCPPolarAxisRadial::stLogarithmic
@ stLogarithmic
Logarithmic scaling with correspondingly transformed axis coordinates (possibly also setTicker to a Q...
Definition: qcustomplot.h:6989
QCPPolarAxisRadial::lmUpright
@ lmUpright
Definition: qcustomplot.h:7005
QCPAxis::ticks
bool ticks() const
Definition: qcustomplot.h:2186
QCPLegend::mIconBorderPen
QPen mIconBorderPen
Definition: qcustomplot.h:5191
QCPPolarAxisAngular::range
const QCPRange range() const
Definition: qcustomplot.h:7261
QCPAxis::mSelectedTickLabelColor
QColor mSelectedTickLabelColor
Definition: qcustomplot.h:2320
QCPLabelPainterPrivate::asTopLeft
@ asTopLeft
Definition: qcustomplot.h:1585
QCPFinancial::getValueRange
virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:27353
QCPPolarLegendItem::getFont
QFont getFont() const
Definition: qcustomplot.cpp:34387
QCPLayerable
Base class for all drawable objects.
Definition: qcustomplot.h:716
QCPItemTracer::mainPen
QPen mainPen() const
Definition: qcustomplot.cpp:30717
QCPItemPixmap::mAspectRatioMode
Qt::AspectRatioMode mAspectRatioMode
Definition: qcustomplot.h:6796
QCPPolarAxisAngular::mRadialAxes
QList< QCPPolarAxisRadial * > mRadialAxes
Definition: qcustomplot.h:7441
QCPTextElement::mFont
QFont mFont
Definition: qcustomplot.h:5286
QCPGraph::getVisibleDataBounds
void getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin, QCPGraphDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const
Definition: qcustomplot.cpp:21934
QCPItemTracer::TracerStyle
TracerStyle
Definition: qcustomplot.h:6836
QCPPolarAxisAngular::setTicker
void setTicker(QSharedPointer< QCPAxisTicker > ticker)
Definition: qcustomplot.cpp:33344
QCPLayoutElement::mMaximumSize
QSize mMaximumSize
Definition: qcustomplot.h:1280
QCPAxisRect::layoutChanged
virtual void layoutChanged() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:18498
QCustomPlot::itemAt
ItemType * itemAt(const QPointF &pos, bool onlySelectable=false) const
Definition: qcustomplot.h:4091
QCPPolarAxisAngular::setSelectableParts
Q_SLOT void setSelectableParts(const QCPPolarAxisAngular::SelectableParts &selectableParts)
Definition: qcustomplot.cpp:33202
QCPErrorBars::setErrorType
void setErrorType(ErrorType type)
Definition: qcustomplot.cpp:28064
QCPItemTracer::setInterpolating
void setInterpolating(bool enabled)
Definition: qcustomplot.cpp:30541
QCPAxis::setLabelPadding
void setLabelPadding(int padding)
Definition: qcustomplot.cpp:8955
QCPTextElement::mTextColor
QColor mTextColor
Definition: qcustomplot.h:5287
QCPAxisRect::rangeZoomAxis
QCPAxis * rangeZoomAxis(Qt::Orientation orientation)
Definition: qcustomplot.cpp:18120
QCPGrid::mZeroLinePen
QPen mZeroLinePen
Definition: qcustomplot.h:2068
QCPAxisTickerPi::mPiValue
double mPiValue
Definition: qcustomplot.h:1975
QCPPolarGraph::setData
void setData(QSharedPointer< QCPGraphDataContainer > data)
Definition: qcustomplot.cpp:34625
QCPAxisTickerDateTime::setDateTimeFormat
void setDateTimeFormat(const QString &format)
Definition: qcustomplot.cpp:6568
QCP::Interaction
Interaction
Definition: qcustomplot.h:272
QCPItemCurve::mSelectedPen
QPen mSelectedPen
Definition: qcustomplot.h:6513
QCPAxis::mRangeReversed
bool mRangeReversed
Definition: qcustomplot.h:2333
QCPColorScale::rangeZoom
bool rangeZoom() const
Definition: qcustomplot.cpp:20153
QCPItemBracket::bsRound
@ bsRound
A brace with round edges.
Definition: qcustomplot.h:6919
QCPGraph::lsImpulse
@ lsImpulse
each data point is represented by a line parallel to the value axis, which reaches from the data poin...
Definition: qcustomplot.h:5479
QCPGraph::mScatterSkip
int mScatterSkip
Definition: qcustomplot.h:5516
QCPLegend::iconSize
QSize iconSize() const
Definition: qcustomplot.h:5142
QCPPolarAxisRadial::spTickLabels
@ spTickLabels
Tick labels (numbers) of this axis (as a whole, not individually)
Definition: qcustomplot.h:6998
QCPSelectionRect::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
Definition: qcustomplot.cpp:2957
QCPLabelPainterPrivate::~QCPLabelPainterPrivate
virtual ~QCPLabelPainterPrivate()
Definition: qcustomplot.cpp:5500
QCustomPlot::addLayer
bool addLayer(const QString &name, QCPLayer *otherLayer=nullptr, LayerInsertMode insertMode=limAbove)
Definition: qcustomplot.cpp:14761
QCPLayer::drawToPaintBuffer
void drawToPaintBuffer()
Definition: qcustomplot.cpp:1166
QCPPolarGraph::addToLegend
bool addToLegend()
Definition: qcustomplot.cpp:34849
QCPItemText::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:29658
QCPLayoutElement::~QCPLayoutElement
virtual ~QCPLayoutElement() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:3221
QCPAxis::marginSideToAxisType
static AxisType marginSideToAxisType(QCP::MarginSide side)
Definition: qcustomplot.cpp:9452
QCPFinancial::width
double width() const
Definition: qcustomplot.h:6194
QCPAxis::subTickLengthIn
int subTickLengthIn() const
Definition: qcustomplot.cpp:8316
QCPPolarAxisRadial::setNumberFormat
void setNumberFormat(const QString &formatCode)
Definition: qcustomplot.cpp:31552
QCPColorMapData::keyRange
QCPRange keyRange() const
Definition: qcustomplot.h:5996
QCPAxisRect::mAxes
QHash< QCPAxis::AxisType, QList< QCPAxis * > > mAxes
Definition: qcustomplot.h:4983
QCPDataSelection::clear
void clear()
Definition: qcustomplot.cpp:2586
QCPPolarGraph::drawLinePlot
virtual void drawLinePlot(QCPPainter *painter, const QVector< QPointF > &lines) const
Definition: qcustomplot.cpp:35062
QCPAxisTickerLog::getSubTickCount
virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:7770
QCPLayout::elementCount
virtual int elementCount() const =0
QCustomPlot::removeGraph
bool removeGraph(QCPGraph *graph)
Definition: qcustomplot.cpp:14453
QCPLabelPainterPrivate::mRotation
double mRotation
Definition: qcustomplot.h:1660
QCPBarsGroup::spacing
double spacing() const
Definition: qcustomplot.h:5705
QCP::stSingleData
@ stSingleData
One individual data point can be selected at a time.
Definition: qcustomplot.h:316
QCPPainter::pmNonCosmetic
@ pmNonCosmetic
0x04 Turns pen widths 0 to 1, i.e. disables cosmetic pens. (A cosmetic pen is always drawn with width...
Definition: qcustomplot.h:491
QCPItemStraightLine::point2
QCPItemPosition *const point2
Definition: qcustomplot.h:6408
QCPLegend::addItem
bool addItem(QCPAbstractLegendItem *item)
Definition: qcustomplot.cpp:19413
QCPAxis::grid
QCPGrid * grid() const
Definition: qcustomplot.h:2222
QCPAxis::getBasePen
QPen getBasePen() const
Definition: qcustomplot.cpp:9745
QCPGraph::LineStyle
LineStyle
Definition: qcustomplot.h:5473
QCPStatisticalBox::mMedianPen
QPen mMedianPen
Definition: qcustomplot.h:5959
QCPColorGradient::gpCandy
@ gpCandy
Blue over pink to white.
Definition: qcustomplot.h:4750
QCPFinancial::widthType
WidthType widthType() const
Definition: qcustomplot.h:6195
QCPLegend::setIconSize
void setIconSize(const QSize &size)
Definition: qcustomplot.cpp:19165
QCP::SignDomain
SignDomain
Definition: qcustomplot.h:207
QCPBars::wtPlotCoords
@ wtPlotCoords
Bar width is in key coordinates and thus scales with the key axis range.
Definition: qcustomplot.h:5797
QCustomPlot::rpRefreshHint
@ rpRefreshHint
Whether to use immediate or queued refresh depends on whether the plotting hint QCP::phImmediateRefre...
Definition: qcustomplot.h:3786
QCPItemEllipse::setBrush
void setBrush(const QBrush &brush)
Definition: qcustomplot.cpp:29979
QCPAxisTickerTime::setTimeFormat
void setTimeFormat(const QString &format)
Definition: qcustomplot.cpp:6916
QCPPolarAxisRadial::mNumberMultiplyCross
bool mNumberMultiplyCross
Definition: qcustomplot.h:7154
QCPLegend::setSelectedBorderPen
void setSelectedBorderPen(const QPen &pen)
Definition: qcustomplot.cpp:19270
QCPAxisTickerTime::mFieldWidth
QHash< TimeUnit, int > mFieldWidth
Definition: qcustomplot.h:1841
QCP::aePlottables
@ aePlottables
0x0020 Main lines of plottables
Definition: qcustomplot.h:240
QCPPolarGraph::mSelectable
QCP::SelectionType mSelectable
Definition: qcustomplot.h:7692
QCPAxisRect::mScaledBackgroundPixmap
QPixmap mScaledBackgroundPixmap
Definition: qcustomplot.h:4970
QCPScatterStyle::setPen
void setPen(const QPen &pen)
Definition: qcustomplot.cpp:10800
QCPPolarAxisAngular::setRangeUpper
void setRangeUpper(double upper)
Definition: qcustomplot.cpp:33299
QCustomPlot::mInteractions
QCP::Interactions mInteractions
Definition: qcustomplot.h:3942
QCPFinancialData::key
double key
Definition: qcustomplot.h:6136
QCPPolarGrid::mParentAxis
QCPPolarAxisAngular * mParentAxis
Definition: qcustomplot.h:7548
QCPAxisRect::bottom
int bottom() const
Definition: qcustomplot.h:4952
QCPColorMap::mGradient
QCPColorGradient mGradient
Definition: qcustomplot.h:6094
QCPPolarAxisRadial::moveRange
void moveRange(double diff)
Definition: qcustomplot.cpp:31886
QCPAxis::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9674
QCPAxisTickerPi::setPiValue
void setPiValue(double pi)
Definition: qcustomplot.cpp:7455
QCPItemStraightLine::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28887
QCPAxisPainterPrivate::labelFont
QFont labelFont
Definition: qcustomplot.h:2409
QCPErrorBars::dataValueRange
virtual QCPRange dataValueRange(int index) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:28188
QCustomPlot::QCPLayer
friend class QCPLayer
Definition: qcustomplot.h:4013
QCPScatterStyle::ssSquare
@ ssSquare
\enumimage{ssSquare.png} a square
Definition: qcustomplot.h:2498
QCPRange::normalize
void normalize()
Definition: qcustomplot.h:820
QCPColorGradient::nhNanColor
@ nhNanColor
NaN data points appear as the color defined with setNanColor.
Definition: qcustomplot.h:4738
QCustomPlot::itemClick
void itemClick(QCPAbstractItem *item, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3867
QCPPolarGrid::setRadialSubGridPen
void setRadialSubGridPen(const QPen &pen)
Definition: qcustomplot.cpp:34222
QCPSelectionDecorator::drawDecoration
virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection)
Definition: qcustomplot.cpp:11170
QCPCurve::addData
void addData(const QVector< double > &t, const QVector< double > &keys, const QVector< double > &values, bool alreadySorted=false)
Definition: qcustomplot.cpp:22743
QCPLabelPainterPrivate::amRectangular
@ amRectangular
Definition: qcustomplot.h:1564
QCPAxisPainterPrivate::CachedLabel::pixmap
QPixmap pixmap
Definition: qcustomplot.h:2434
QCPPolarLegendItem
A legend item for polar plots.
Definition: qcustomplot.h:7575
QCPLayoutGrid::addElement
bool addElement(int row, int column, QCPLayoutElement *element)
Definition: qcustomplot.cpp:4159
QCPAbstractItem::rectDistance
double rectDistance(const QRectF &rect, const QPointF &pos, bool filledRect) const
Definition: qcustomplot.cpp:13130
QCPColorMap::mInterpolate
bool mInterpolate
Definition: qcustomplot.h:6095
QCPLayerable::parentLayerable
QCPLayerable * parentLayerable() const
Definition: qcustomplot.h:733
QCPLegend::mSelectedBorderPen
QPen mSelectedBorderPen
Definition: qcustomplot.h:5198
QCPPolarAxisRadial::mLabelFont
QFont mLabelFont
Definition: qcustomplot.h:7143
QCPMarginGroup::removeChild
void removeChild(QCP::MarginSide side, QCPLayoutElement *element)
Definition: qcustomplot.cpp:3134
QCPAxis::deselectEvent
virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9497
QCPAxisRect::setRangeZoomAxes
void setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical)
Definition: qcustomplot.cpp:18314
QCPPolarAxisRadial::setTickLengthIn
void setTickLengthIn(int inside)
Definition: qcustomplot.cpp:31636
QCustomPlot::mScaledBackgroundPixmap
QPixmap mScaledBackgroundPixmap
Definition: qcustomplot.h:3947
QCPPolarAxisRadial::scaleRange
void scaleRange(double factor)
Definition: qcustomplot.cpp:31911
QCPPolarAxisAngular::mTickVectorLabels
QVector< QString > mTickVectorLabels
Definition: qcustomplot.h:7446
QCPPolarAxisRadial::mSubTickLengthOut
int mSubTickLengthOut
Definition: qcustomplot.h:7158
QCPItemBracket::bsCurly
@ bsCurly
A curly brace.
Definition: qcustomplot.h:6920
QCPColorMap::selectTest
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:26632
QCP::ruDotsPerInch
@ ruDotsPerInch
Resolution is given in dots per inch (DPI/PPI)
Definition: qcustomplot.h:188
QCustomPlot::axisClick
void axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
Definition: moc_qcustomplot.cpp:3881
QCPItemText::mainBrush
QBrush mainBrush() const
Definition: qcustomplot.cpp:29898
QCPTextElement::setSelectedFont
void setSelectedFont(const QFont &font)
Definition: qcustomplot.cpp:19833
QCPAxis::wheelEvent
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:9619
QCPItemEllipse::draw
virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:30023
QCPPolarAxisAngular::mSelectedTickPen
QPen mSelectedTickPen
Definition: qcustomplot.h:7432
QCPPolarGrid::mRadialAxis
QPointer< QCPPolarAxisRadial > mRadialAxis
Definition: qcustomplot.h:7549
QCustomPlot::mPlottables
QList< QCPAbstractPlottable * > mPlottables
Definition: qcustomplot.h:3937
QCPAxis::QCPAxis
QCPAxis(QCPAxisRect *parent, AxisType type)
Definition: qcustomplot.cpp:8196
QCPColorScale::~QCPColorScale
virtual ~QCPColorScale() Q_DECL_OVERRIDE
Definition: qcustomplot.cpp:20121